perm filename SCNSER.MAC[IP,SYS]1 blob sn#699454 filedate 1983-03-08 generic text, type T, neo UTF8
TITLE SCNSER - TERMINAL SCANNER SERVICE  V1575
SUBTTL R CLEMENTS/RCC/DAL/PMW/EJW/WRS	22 JUL 80
	SEARCH	F,S
IFN FTNET,<SEARCH NETPRM>
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
XP VSCNSR,1575
ENTRY SCNSER
SCNSER::


;               TABLE OF CONTENTS FOR SCNSER
;
;
;                        SECTION                                   PAGE
;    1. PARAMETER AND CONFIG DEFINITIONS..........................   2
;    2. DATA STRUCTURES
;         2.1   LINTAB AND DSCTAB.................................   4
;         2.2   LINE DATA BLOCK (LDB).............................   5
;    3. MACROS TO MANIPULATE TERMINAL BUFFER STREAMS..............  13
;         3.3   TTY DEVICE DATA BLOCK (DDB).......................  16
;    4. TRANSMIT INTERRUPT ROUTINE................................  17
;    5. RECEIVE INTERRUPT ROUTINE.................................  30
;    6. KI10 CONSOLE TERMINAL SERVICE.............................  55
;    7. FILLERS AND SIMULATION ROUTINES...........................  56
;    8. TIMING ROUTINE............................................  68
;    9. CHUNK HANDLERS............................................  84
;   10. CHUNK HANDLERS
;        10.1   ALLOCATION AND DEALLOCATION.......................  85
;        10.2   CLEAR BUFFERS.....................................  86
;   11. UUO LEVEL ROUTINES FOR BUFFERED I/O.......................  87
;   12. DDT MODE CALLI'S..........................................  94
;   13. TTCALL AND TRMOP.
;        13.1   TTCALL DISPATCH...................................  95
;        13.2   OUTCHR AND IMAGE OUTCHR...........................  97
;        13.3   OUTSTR AND RESCAN.................................  98
;        13.4   SKPINL AND SKPINC.................................  99
;        13.5   GETLIN............................................ 100
;        13.6   SETLIN, INCHSL, INCHWL, INCHRS & INCHRW........... 101
;        13.7   TRMNO. UUO........................................ 102
;        13.8   TRMOP. DISPATCH................................... 103
;        13.9   SKIPS AND CLEARS.................................. 111
;        13.10  TRMOP. I/O........................................ 112
;        13.11  TRMOP. I/O SUBROUTINES............................ 113
;        13.12  TRMOP. DATASET FUNCTIONS.......................... 114
;   14. BYTE POINTERS INTO THE USER'S LDBMIC WORD................. 118
;   15. TYPE
;        15.1   - TYPE A STRING ON BEHALF OF A USER............... 119
;   16. CLEAR/SET
;        16.1   - CLEAR DOWN LDBMIC/SET UP LDBMIC................. 120
;   17. GET
;        17.1   GET THE STATUS FROM THE USERS LDBMIC WORD......... 121
;   18. RESPONSE
;        18.1   - RECORD AN ERROR MESSAGE......................... 122
;   19. LOG
;        19.1   - RECORD ALL UUO LEVEL OUTPUT..................... 123
;   20. SUBROUTINES CALLED FROM SCNSER AND OTHER PLACES........... 124
;   21. SUBROUTINES FOR I/O....................................... 128
;   22. COMMAND LEVEL ROUTINES.................................... 136
;   23. SUBROUTINES FOR COMCON OR UUO LEVEL....................... 149
;   24. ROUTINES FOR PTY.......................................... 169
;   25. IMPURE DATA............................................... 173
	SUBTTL	PARAMETER AND CONFIG DEFINITIONS

XP STTYBF,20

;DATASET TRANSACTION CODES FROM SCNSER TO/FROM XXXINT'S

XP DSTOFF,1		;DSCREC OR DSCTYP
XP DSTON,2		;DSCREC OR DSCTYP
XP DSTRNG,3		;DSCREC
XP DSTREQ,3		;DSCTYP
XP DSTINI,4		;TO AND FROM. SENDING COMPUTER WAS RESTARTED.
XP DSTSTS,5		;REQUEST DATA SET STATUS
XP DSTCRQ,10		;CALL REQUEST TO MODEM. WANT TO DIAL OUT.
XP DSTPND,20		;PRESENT NEXT DIGIT, TO AND FROM.
; NOTE - TO MODEM, 20-37 MEAN SEND DIGIT N-20
; WHERE DIGIT 17 MEANS END OF NUMBER (TO BOTH HARDWARE AND SOFTWARE)
; AND DIGIT 16 MEANS 5-SECOND DELAY TO SOFTWARE, FOR SECOND DIAL TONE.
XP DSTNAC,40		;NO ACTION -SYSINI (ONLY USER OF DSTREQ) SHOULD
			; NOT MODIFY LINE STATUS CODES (CARRIER ON/OFF)

;LINE CONTROL TRANSACTION CODES

XP LNTEHC,1	;ENABLE HUNG CHECK
XP LNTDHC,2	;DISABLE HUNG CHECK
IFNDEF STDALT,<STDALT==033>		;VALUE OF STANDARD ALTMODE
IFNDEF VTAB,<VTAB==10>			;VERTICAL TAB SPACING (MUST BE POWER OF 2)

ND	TTIBRK,↑D132			;MAX CHARS BEFORE BREAK CONDITION
ND	TTIWRN,TTIBRK+↑D40		;MAX CHARS BEFORE WE SEND AN XOFF
ND	TTIMAX,↑D300			;MAX CHARS BEFORE WE START TO SSIN??

IFNDEF FTMLOG,<XP FTMLOG,-1>		;NON-ZERO TO INCLUDE MIC LOG CODE

;SIZE OF CHUNKS

XP IMGTIM,↑D10		;MUST FIT IN LDPTIM FIELD. HUNG TIME FOR IMI


;HARDWARE PARAMETERS OTHER THAN THOSE IN THE XXXINT ROUTINES

CTY=120		;HARDWARE DEVICE NUMBER OF THE KA10 CONSOLE TERMINAL
	SUBTTL	DATA STRUCTURES -- LINTAB AND DSCTAB


;DATA STRUCTURES IN COMMON

;LINTAB:	BLOCK # OF LINES INCLUDING SCANNER,CTY AND PTY'S
;EACH WORD=	RH= LDB ADR
;		LH13-17=0 (FOR @ LINTAB)
;		LH 0-12 ARE COPIED INTO LDBDCH PERMANENT BITS BY LDBCLR
;		POINTER = LNPVRG

;DSCTAB:	BLOCK # OF DATASETS NEEDING TIMING
;		RH= LINKED TERMINAL LINE NUMBER FOR DATA
;		LH= TIME IN 14-17, ALSO DSCHWC,DSCSWC,DSCFAI

IFN FTMODM,<
XP DSCHWC,400000	;WHEN LAST HEARD FROM, THE HARDWARE CARRIER WAS ON
XP DSCSWC,200000	;THE SOFTWARE CONSIDERS THE CARRIER TO BE ON OR
			; TO BE COMING ON IMMINENTLY
XP DSCFAI,100000	;CARRIER WENT OFF, BUT MAY BE BRIEF FAILURE
			; EXCEPT FOR GPO 2B MODEM, MUST QUIT IMMEDIATELY
XP DSCNCR,040000	;NEW CARRIER FLAG, ON FOR FRACTION OF SECOND FOR CLOCK SYNC
XP DSCBLI,020000	;BLIND FLAG - IGNORE EVERYTHING FOR 1 SEC AFTER CARRIER ON
XP DSCDLW,010000	;DIALLER WAIT. WAITING FOR RESULTS FROM DIALLER
XP DSCDLF,004000	;DIALLER FAIL. UNSUCCESSFUL DIALLER ATTEMPT
XP DSCDLC,002000	;DIALLER COMPLETE. SUCCESSFUL DIALLER ACTION.
XP DSCEON,001000	;END OF NUMBER. SENT ALL DIGITS TO DIALLER.
XP DSCTMM,77		;TIME MASK. MUST AGREE WITH DSTIMP POINTER.

;DEFINITIONS FOR INITIALIZATION ROUTINE IN SYSINI

XP DSCICL,DSCHWC!DSCSWC!DSCFAI!DSCDLW!DSCDLF!DSCDLC!DSCEON!DSCTMM
XP DSCIC1,DSCHWC!DSCSWC
XP DSCIC2,DSCTMM!DSCFAI!DSCDLW!DSCDLF!DSCDLC!DSCEON

> ;END OF FTMODM CONDITIONAL
	SUBTTL	DATA STRUCTURES -- LINE DATA BLOCK (LDB)

;PROTOTYPE LINE DATA BLOCK FOR A TTY (OR PTY) LINE

SCNLDB::
PHASE 0

LDBDDB::!XWD	ZERO5,0	;ADDRESS OF LINE'S ATTACHED DDB, IF ANY
XP LDBCMR,400000	;SIGN BIT OF LDBDDB IS COMMAND REQUEST BIT
			; MUST BE IN WORD ZERO, FOR @U, 13-17 MUST BE ZERO
XP LDBCMF,200000	;COMMAND FORCED. MEANS TYI ATE A CONTROL C
			; WHICH WAS DESTINED FOR COMCON, OR SOME OTHER COMMAND
			; IS TO BE FORCED, VIA LDPCMX. MUST BE IN SAME
			; WORD AS LDBCMR
XP LDBCMK,100000	;FORCING KJOB COMMAND
XP LDBDET,40000		;JOB DETACHED FROM THIS LINE DURING COMMAND
			;PROCESSING.  FORCE CLEANUP OF JOB/COMMAND
			;AT NEXT TICK.
			;BITS 9-12 ARE INDEX FOR FORCED COMMAND, 
			; POINTER = LDPCMX

LDICLR::!		;ON RESTART, START CLEARING HERE
LDBBKU:!0		;COPY OF LDBTIP AT LAST BREAK RECINT
LDBTIP::!0		;T2 TO PUT CHARACTERS IN INPUT BUFFER
LDBTIT::!0		;T2 TO TAKE CHARACTERS FROM INPUT BUFFER
LDBTIC::!0		;COUNT OF ECHOED CHARACTERS IN INPUT BUFFER
LDBBKC::!0		;COUNT OF BREAK CHARACTERS IN INPUT BUFFER
LDBTOP::!0		;T3 TO PUT CHARACTERS IN OUTPUT BUFFER
LDBTOT::!0		;T2 TO TAKE CHARACTERS FROM OUTPUT BUFFER
LDBTOC::!0		;COUNT OF CHARACTERS IN OUTPUT BUFFER
LDBECT::!0		;T2 TO TAKE CHARACTERS FROM INPUT FOR ECHOING
LDBECC::!0		;COUNT OF CHARACTERS TO ECHO
LDBCLP::!0		;COMMAND LINE POINTER (FOR COMCON)
LDBXNP::!0		;XON CLASS CHARACTER POINTER FOR OUTPUT
LDBFLP::!0		;FILLER CHARACTER POINTER FOR OUTPUT
LDBPBK::!0		;WORD OF UP TO 4 BREAK CHARACTERS (8 BIT)
			;FOR PACKED IMAGE MODE (PIM); SET WITH TRMOP 2037
LDBHPS::!0		;HORIZONTAL POSITION COUNTER.  COUNTS UP FROM
			;MINUS CARRIAGE WIDTH TO ZERO.
IFN FTRSP!FTACCT,<
LDBBCT::!0		;TOTAL COMMAND,,BREAK CHARACTER COUNT
LDBICT:!0		;TOTAL INPUT CHARACTER COUNT
LDBOCT:!0		;TOTAL OUTPUT CHARACTER COUNT
> ;END IFN FTRSP!FTACCT

LDICLE==:.-1		;ON RESTART, CLEAR THRU HERE
;MORE OF THE PROTOTYPE LINE DATA BLOCK
LDBDCH::!0		;DEVICE CHARACTERISTICS BITS

;BITS IN LH OF LDBDCH (CARRIED IN LH OF U DURING INTERRUPT ROUTINE)
;ORDER OF FIRST SEVERAL BITS IS IMPORTANT  --  SEE XMTSPC!

LDLIDL==:400000		;LINE IS IDLE.  IF CLEAR, WE ARE EXPECTING
			;A TRANSMIT INTERRUPT
			; MUST BE SIGN BIT.
LDLSTP==:200000		;OUTPUT WAS STOPPED BY CTRL/S
LDLSSO==:100000		;SCNSER STOPED OUTPUT. (HIT A TTY PAGE N BREAK)
LDLFCP==:040000		;A FORCE CHARACTER OR FILLERS ARE PENDING
			;NOTE! THIS BIT CAN BE SET WITH OUT FEAR IF ONE
			; WISHES TO HAVE XMTRDY SKIP RETURN, BUT IS NOT SURE
			; THAT A CHAR IS AVAILABLE. (SEE TTYDRQ)
LDLPIM==:020000		;TERMINAL WAS OPENED IN PIM MODE
LDLMIC==010000		;LDBMIC IS NON-ZERO
LDLDLR==004000		;SUPPRESS DOLLAR SIGN ON ALTMODES.
LDLNEC==:002000		;NO ECHO, DUE TO PROGRAM
LDLFCS==:001000		;LINE INITED IN FULL CHAR SET MODE
LDLIMI==:000400		;IMAGE INPUT (KEEP NULLS)
XP LDLCOM,000200	;LINE IS AT COMMAND LEVEL
LDLBKA==:000100		;BREAK ON ALL CHARACTERS (DDTIN, TTCALL)

;*** BEGINNING OF GROUP OF BITS POINTED TO BY LDPVR1 ***
;*** BEGINNING OF 4 BITS POINTED TO BY GETLP1 FOR GETLIN ****
XP LDLSLV,000040	;SLAVE. THIS TERMINAL MAY BE ASSIGNED.
XP LDLLCT,000020	;LOWER CASE TRANSLATE TO UPPER
XP LDLTAB,000010	;LINE ACCEPTS TABS, NOT SPACES.
XP LDLLCP,000004	;LOCAL COPY (NO ECHO)
;*** END OF BITS POINTED TO BY GETLP1 ***
XP LDLFRM,000002	;LINE ACCEPTS FF AND VT (ELSE USE LF'S)
XP LDLNFC,000001	;NO FREE CARRIAGE RETURN AT 72 COLUMNS
;*** END OF GROUP FOR LDPVR1 ***
XP LDLECH,LDLNEC!LDLBKA!LDLLCP

;BITS TO BE CLEARED ON A 140 RESTART
ZZL==LDLIDL+LDLIMI+LDLSTP+LDLSSO+LDLNEC+LDLFCP+LDLDLR+LDLBKA+LDLPIM+LDLMIC+LDLFCS
XP LDLIIF,LDLIMI+LDLFCS		;IMAGE INPUT OR FULL CHAR SET MODE
;RH OF LDBDCH - BITS 27-35 = LINE NUMBER, POINTER = LDPLNO

LDRPTY==:400000		;PSEUDO-TERMINAL
LDRCTY==:200000		;CONSOLE TERMINAL
;*** START OF GROUP OF BITS POINTED TO BY LDPVR2 ***
LDROSU==:100000		;OUTPUT SUPPRESS (↑O)
LDRDSD==:040000		;DATASET DATA LINE
LDR274==:020000		;LINE IS A 2741
LDRHLF==010000		;HALF DUPLEX LINE (TWX OR DC10C)
LDRRMT==:004000		;REMOTE NON-DATASET LINE
XP LDRDSR,LDRDSD+LDRRMT	;REMOTE OR DATA SET LINE (FOR PATCH)
			; SO CAN'T ATTACH TO PROJECT 1 #
;*** END OF GROUP FOR LDPVR2 ***
LDRREM==:002000		;TERMINAL AT REMOTE STATION
LDRSHC==:001000		;SUPPRESS HUNG CHECK -I.E. DON'T FORCE CHAR'S OUT
			;  WHEN NO XMIT FLAG.--SET BY 680 FOR SPECIAL
			;  DEVICES (E.G. 2741) & ITS OPR. TERMINAL

IFN FTCIMP,<		;[arpa]
 XP LDRIMP,000400	;[arpa] TTY IS AN ITY (IMP TTY)
			;[arpa] STOLEN BIT - DEC RESERVES 9 BITS FOR LINE NUMBER,
			;[arpa] BUT WE ONLY USE 8, AND THIS BIT MUST BE IN THE
			;[arpa] SAME HALF WORD AS LDRPTY.
XP LDRPTI,LDRPTY!LDRIMP	;[arpa] LINE IS A  PTY OR IMP TTY
> ;END IFN FTCIMP	;[arpa]

;BITS TO BE CLEARED ON A 400 RESTART
ZZR==LDRPTY+LDRCTY+LDRSHC+LDROSU

;DEFINITIONS OF BITS FOR GETLIN UUO, CLOSELY ASSOCIATED WITH ABOVE

GTLRDY==100		;BIT FOR GETLIN TO INDICATE WAITING BREAK CHAR
GTLT37==20		;MODEL 37 BIT (COPY OF LDLLCT)
GTLT35==10		;MODEL 35 BIT (COPY OF LDLTAB)
GTLLCP==4		;LOCAL COPY (OLD FULTWX) (COPY OF LDLLCP)
GTLXON==2		;XON IS TRUE (COPY OF L2RXON)
GTLMSK==LDR274!777	;BITS TO CLEAR ON GETLIN
LGLSET==GTLT37+GTLT35+GTLLCP+GTLXON	;MAY BE SET BY SETLIN


;BITS THAT ARE TESTED ON A CALL TO XMTCHR TO SEPARATE OUT
;THE NORMAL CASE FROM THE SPECIAL CASES.

DCHSPC==LDLIDL+LDLSTP+LDLSSO+LDLPIM+LDLFCP+LDLMIC,,LDRHLF

;MORE OF THE PROTOTYPE LINE DATA BLOCK

LDBOFL::!
LDBBYT::!0		;A WORD OF BYTES FOR THIS LINE

;BITS	POINTER	USE
;35-28	LDPECK	ECHO CHECK FOR HALF DUPLEX LINES
;27	L1RDEM	DEFERRED ECHO BIT.  SET BY SET TERMINAL DEFER
;26	L1RDEC	ECHO MAY ECHO 1 CHARACTER IF DEFERRED
;25	L1RDEL	ECHO MAY ECHO 1 LINE IF DEFERRED
;24-22	LDPCPU	CPU NUMBER--
;21	L1RCHP	CHANGE HARDWARE PARAMETERS FLAG (MEANINGUL EVEN FOR PTYS!)
;20	L1RMIF	MIC INTERLOCK FLAG
;19-15	LDPTIM	TIMEOUT ON IMAGE INPUT
;14-06	LDPSVC	SAVE CHARACTER DURING FREE CRLF, ↑X, ETC.
;05-03	POHPOS	OLD HORIZONTAL POSITION. NEEDED FOR TAB SIMULATION
;02-01	LDPFLC	COUNT OF NUMBER OF FILLERS BY CLASS
;0		1 IF FRONT END FOR THIS LINE IS DOWN.
;		 USE LDBOFL AS THE SYMBOL TO SKIPGE/SKIPL ON.
L1LOFL==:400000		;THE OFF-LINE BIT
L1RDEM==:1B27		;DEFERRED ECHO MODE
L1RDEC==:1B26		;MAY ECHO ONE CHARACTER (DEFERRED ECHO ONLY)
L1RDEL==:1B25		;MAY ECHO ONE LINE (DEFERRED ECHO ONLY)
L1RCHP==:1B21		;CHANGE HDW PARMS
L1RMIF==:1B20		;MIC INTERLOCK FLAG
LDIBCM==477777,,600000+L1RDEM+L1RDEC+L1RDEL+L1RCHP+L1RMIF+377 ;MASK TO CLEAR LDBBYT AT TTYINI. ALL ARE CLEARED
			; EXCEPT LDPFLC

;ANOTHER BYTE WORD, FLAGS AT LEFT.
LDBBY2::!0
;BITS	POINTER	USE
;35-28	LDPRCS	MOST RECENT RECEIVED CHARACTER
;20-27	LDPWID	WIDTH OF TERMINAL CARRIAGE
;18-19	BITS - SEE BELOW
;9-17	LDPDSC	DATASET CONTROL TABLE INDEX BACK POINTER
;0-8	BITS - SEE BELOW

L2LDEL==:400000		;LAST CHAR IN WAS A DELETE
L2LCCS==200000		;LAST CHAR IN WAS A ↑C
L2LHD1==100000		;XMT DONE FLAG SEEN THIS CHAR ON HDX LINE
L2LHD2==040000		;RCV DONE FLAG SEEN THIS CHAR ON HDX LINE
L2LHD3==020000		;IGNORING RCV INTS DUE TO ECHO CHECK ERR ON HDX LINE
L2LHD4==010000		;NEXT RCV INT WILL BE CUE AFTER ECHO CHK
L2LHD5==004000		;RECEIVE ECHO WAS IN FACT NOT SAME AS XMT CHAR
L2LSND==:002000		;SEND ALLOWED WHILE BUSY
L2LTAP==:001000		;↑Q FROM KEYBOARD TURNS ON L2RXON. SET BY .TERMINAL TAPE COMMAND

L2LHDM==L2LHD1!L2LHD2!L2LHD3!L2LHD4!L2LHD5

L2LCLR==L2LDEL!L2LCCS!L2LHDM!L2LSND!L2LTAP
			;CLEARED ON INITIALIZATION

L2RXON==:400000		;XON IS TRUE (PAPER TAPE INPUT)
L2RECS==200000		;EAT COMMAND SYNC, FOR TTCALL 10
IFN FTCIMP,<			;[arpa]

;[arpa] IMP DEVICE INFORMATION

LDBIMP::0		;[arpa] IF NON-ZERO, POINTER TO IMP DDB ADDR FOR CROSSPATCH


LDBQUO::0		;[arpa] QUOTE/ESCAPE CHARS AND DATA

;[arpa] (byte pointers and bits are defined and mostly used in TCPSER)
;[arpa] BITS	POINTER	USE

;[arpa] 29-35	LDPQUO	QUOTE CHARACTER(INITIAL VALUE ↑N)
;[arpa] 22-28	LDPSFT	CASE SHIFT CHARACTER (NO INITIAL VALUE)
;[arpa] 15-21	LDPLCL	LOCAL TELNET ESCAPE (INITIAL VALUE ↑← OR ↑?)
;[arpa] 08-14	LDPNET	NETWORK ESCAPE CHARACTER (NO INITIAL VALUE)
;[arpa] 00-03	  INDICATOR BITS:
;[arpa]	03		LQLNet	network escape typed
;[arpa]	02		LQLDwn	shift mode (0=up, 1=down)
;[arpa]	01		LQLSft	previous character was shift char.
;[arpa]	00		LQLQuo	previous character was quote char (sign bit)

> ;[arpa] END FTCIMP
IFN FTLINK,<			;[link]

;[link] TERMINAL LINK INFORMATION

;[link] BITS ARE DEFINED IN S.MAC FOR EASE OF USE BY BOTH SCNSER AND LNKSER

EXTERN	LNKSER		;[link] FORCE LINK LOADER TO INCLUDE LINK CODE

LDBLNK::0		;[link]

;[link] BITS	NAME	POINTER	USE

;[link] 0	LNKXMT		TTY IS ABOUT TO TRANSMIT BECAUSE OF LINK
;[link] 1	LNKACV		TTY HAS ACTIVE LINKS
;[link] 2	LNKREF		TTY IS REFUSING FURTHER LINKS
;[link] 3-11		LNKPTR	HEAD OF LINKED LIST OF LINKED TTY'S (LNKTBL IN COMMON)
;[link] 12	LNKECH		SENDING ECHO CHAR TO LINKED TTY
;[link] 13	LNKFLP		SEND INPUT FILLS TO LINKED TTY (LDBFLP)
;[link] 14	LNKOPD		ON CLOCK TICK, START OUTPUT TO THIS TTY IF NOT ACTIVE

LDBLKB::0	;[link] HEAD/TAIL OF LINKED LIST OF ECHO CHARACTERS IN
		;[link] INTERMEDIATE BUFFER. SEE LNKGET/LNKPUT IN LNKSER.

;[link] LOCATIONS EXTERNAL TO LNKSER:

INTERN	LDPSVC,FLLFLG,RCHLT1,LDBFLP
INTERN	LDBDCH,LDLIDL,LDBTOP,LDBTOT,TYOVRG
> ;[link] END FTLINK
;PAGE COUNTER WORD AND PAGE FLAGS
LDBPAG::!0
;BITS	POINTER USE
;30-35	LDPPCT	PAGE COUNTER
;24-29	LDPPSZ	PAGE SIZE
;18-23	LDPPFF	#LF'S REMAINING ON F.F. SIMULATION
;10-17	LDPACR	AUTO CRLF COUNTER
;8		WE ARE FORCING XMIT START VIA TOPOKE
;7	LDPDIS	TERMINAL IS A DISPLAY TERMINAL (HANDLES <DEL>'S)
;6		SEND ALL PENDING
;5		DON'T OUTPUT ANY MORE SINGLE L.F.'S
;4		SUPPRESS BLANK LINES (SET TERMINAL NO BLANK)
;3	LDPALT	ALTMODE CONVERSION (SET TERMINAL ALT)
;2		AN XOFF WAS SENT, XON NEEDED SOMETIME
;1		SET TERMINAL PAGE HAS BEEN DONE
;0		TERMINAL HAS NOT BEEN HEARD FROM IN THIS SECOND

LPLIRM==400000		;LOST TRANSMIT INTERRUPT BIT
LPLPAG==:200000		;SET TERMINAL PAGE COMMAND WAS EXECUTED
LPLXOF==100000		;SENT XOFF, ALWAYS SEND AN XON LATER
LPLALT==:40000		;ALTMODE CONV. (1:CONVERT 175,176 TO 033)
LPLBLK==:20000		;SUPPRESS BLANK LINES
LPLSLF==10000		;SUPPRESS LINE FEEDS
LPLSAP==:4000		;SEND ALL PENDING
LPLDIS==:2000		;SET IF THIS IS A DISPLAY TERMINAL
			; I.E., BACKSPACE MOVES CURSOR BACKWARDS
			; SPACE "ERASES" CHARACTER ON SCREEN
			; TERMINAL HAS ABILITY TO "HOME UP" CURSOR
LPLPOK==1000		;WE ARE FORCING XMIT START VIA TOPOKE (PREVENT RACE)
LPLACR==377		;AUTO CRLF COUNTER
LPLCLR==LPLIRM!LPLXOF!LPLBLK!LPLSLF!LPLSAP!LPLACR  ;CLEARED BY LDBINI
;FLAGS AND POINTER TO INTERUPT SERVICE ROUTINES
LDBISR::!BLOCK	1	
;BITS	POINTER	USE
;0	N/A	1 IF THE FRONT END IS CLEVER, 0 IF DUMB
;1-4	LDPTSP	TRANSMIT SPEED
;5-8	LDPRSP	RECEIVE SPEED
;9	LDPAPL	APL MODE
;10	LDPDBK	DEBREAK FEATURE EXISTS
;11	LDPRTC	CONTROL-R, CONTROL-T COMPATIBILITY
;12	LDPTDY	USER SAID "SET TERMINAL TIDY"
;13-17	CONTAIN T1 FOR @LDBISR(U)
;18-35	ADDRESS OF ISR DISPATCH TABLE

LILCFE==:(1B0)		;CLEVER FRONT END
LILRSP==:(17B4)		;RECEIVE SPEED
LILTSP==:(17B8)		;TRANSMIT SPEED
LILAPL==:(1B9)		;APL MODE
LILDBK==:(1B10)		;LINE HAS DEBREAK
LILRTC==:(1B11)		;CONTROL-R, CONTROL-T ARE PASSED TO PGM
LILTDY==:(1B12)		;DO NOT EXPAND OUTPUT

;FUNCTIONS ARE
ISRTYP==:0		;OUTPUT DATA IN T3 ON LINE POINTED TO BY U
ISRDSC==1		;DATA SET CONTROL
ISRCHK==:2		;TEST FOR LOST PIA
ISRINI==:3		;INIT ISR
ISRCHP==:4		;CHANGE HARDWARE PARAMETERS
ISRLPC==:5		;SEND LINE PARAMETER CONTROL MSG
ISRELE==:6		;SET ELEMENT #
ISRREM==:7		;DO REMOTE TERMINAL STUFF
ISROFL==:10		;SKIP IF FRONT END ON LINE

;LDBQUE -- QUEUED PROTOCOL WORD

LDBQUE::BLOCK	1

;BITS
;0-17		QUEUE HEADER
;18-36		NEXT LINE IN QUEUE

;TERMINAL TYPE WORD

LDBTTW::BLOCK	1
;0-7	LDPLCH	LAST CHAR READ BY COMCON.
;8		FREE
;9	LDLFSP	FULL SCNSER PTY
;10	LDLUAR	ON IF PROCESSING CONTROL R
;11	LDLUAW	ON IF PROCESSING CONTROL W
;12	LDLNAN	ON IF AN ALPHA-NUMERIC WAS SEEN WHILE PROCESSING CONTROL W
;		STOP ON SPACE OR TAB
;13-20	LDPFCT	FILLER REPEAT COUNTER
;21-28	PRPOS	POSITION OF PROMPT
;29-35	LDPTTT	TERMINAL TYPE AS SPECIFIED BY TTY TYPE COMMAND

LDLFSP==:400	;FULL SCNSER PTY
LDLUAR==200	;CONTROL R IN PROGRESS
LDLUAW==100	;CONTROL W IN PROGRESS
LDLNAN==40	;ON IF AN ALPHA-NUMERIC CHARACTER HAS BEEN SEEN


IFN FTD10H,<
;FLAGS FOR 2741 SUPPORT
LDBBCD::BLOCK	1
>
;FIVE WORDS FOR REMOTE STATION TERMINAL STATUS

IFN FTNET,<			;NETWORK RELATED LDB FIELDS

LDBREM::BLOCK	5		;WORDS REQUIRED FOR REMOTE TERMINALS

;			LAYOUT OF LDBREM FIELDS
;
; +0	BYTE (19)BITS-USED-BY-NETTTY, (1)0, (16)LAST-DAP-STATUS-MESSAGE-SENT
; +1	BYTE (36)LAST-CHARACTERISTICS-MESSAGE-SENT
; +2	BYTE (14)SLA, (14)DLA, (8)REMOTE-LINE-NUMBER
; +3	BYTE (4)2741-ELEMENT-NUMBER, (8)DRQ-COUNT, (8)EPM-SERIAL, (16)NODE-#
; +4MCR	BYTE (9)NEXT-CHAR-TO-OUTPUT, (9)DISCONNECT-TIMER, (9)JOB, (9)UNUSED
; +4VTM	BYTE (16)DELAYED-STATUS-MESSAGE, (2)0, (18)VTM-QUEUE-LINK


;DEFINE SYMBOLS FOR SOME LDBREM ENTRIES
LDBCCH==:LDBREM+1		;COMPRESSED CHARACTERISTICS WORD
LDBVTQ==:LDBREM+4		;NETVTM'S QUEUE LINK HALF-WORD

;			BITS USED IN LDBREM

;BITS USED BY BOTH NETVTM(LOCAL SET HOST) AND NETMCR(REMOTE TERMINALS)

LRLVTM==:(1B0)			;*** MUST BE SIGN BIT ***
				;  IF SET, THEN THIS IS A "LOCAL TERMINAL"
				;  THAT HAS "SET HOSTED" TO ANOTHER HOST.
LRLCON==:(1B1)			;IF SET, THEN TERMINAL IS "CONNECTED"
				;  (I.E. NCL CONNECT SEQUENCE IS COMPLETE)
LRLSTS==:(1B2)			;IF SET, THEN A "STATUS" MESSAGE IS REQUIRED
				;  SAME BIT, BUT DIFFERENT MSGS FOR VTM & MCR

;BITS USED ONLY BY NETVTM (LOCAL "SET HOST")

LRLSCH==:(1B3)			;IF SET, THEN A "CHARACTERISTICS" MESSAGE
				;  IS REQUIRED (WORKS LIKE "LRLSTS")
LRLDST==:(1B4)			;A "DELAYED" STATUS MESSAGE IS REQUIRED
				;  (USED TO OPTIMIZE MESSAGE TRAFFIC.
				;  THIS BIT HAS PRIORITY OVER LRLSTS)
LRLQED==:(1B5)			;IF SET, THEN VTM LINE HAS BEEN "QUEUED"
				;  BY "VTMENQ"
LRLDIP==:(1B6)			;IF SET, THEN WE HAVE/WANT-TO INITIATE A 
				; DISCONNECT ON THIS LINE
;BITS USED ONLY BY NETMCR ("NORMAL" REMOTE TERMINALS .. ALA DN87)

LRLTTO==:(1B3)			;LDPCHR HAS THE NEXT CHAR TO OUTPUT. THIS IS
				; NECESSARY SINCE THERE IS NO WAY TO TELL IF
				; XMTCHR WILL GIVE A CHAR WITH OUT GETTING IT.
LRLTTW==:(1B4)			;LINE IS WAITING FOR A DATA-REQUEST
LRLSCG==:(1B5)			;↑O ACTION REQUESTED (SEND CHAR GOBBLER)
LRLEPW==:(1B6)			;ECHO PIPELINE MARKER WAITING TO GO.
LRLIMO==:(1B7)			;INDICATES THAT REMOTE IS IN IMAGE MODE OUTPUT
LRLADR==:(1B8)			;USE OF THE AUTO-DIALER HAS BEEN REQUESTED
LRLXOF==:(1B9)			;AN XOFF (↑S) MESSAGE HAS BEEN REQUESTED
LRLCHR==:(1B10)			;THIS TERMINAL HAS RECEIVED AT LEAST 1
				; CHARACTERISTICS MSG.  (SEE NETTTY.MAC, ROUTINE
				; SCNMCR FOR DETAILS OF THE RACES INVOLVED...)
LRLDTR==:(1B11)			;RING/CARRIER BIT (SET/CLEARED BY STATUS MSGS
				; FROM THE -11)
LRLDSR==:(1B12)			;THE -10'S COPY OF WHAT IT THINKS LRLDTR
				; SHOULD BE.  (KEPT SO WE CAN TELL IF THE -11
				; CHANGED IT WHILE WE WEREN'T LOOKING)
LRLDSL==:(1B13)			;THIS LINE IS A DATA-SET LINE
LRLATO==:(1B14)			;INDICATES THAT THIS LINE POSSESSES THE AUTO-
				; BAUD CAPABILITY.  (SET/CLEARED BY THE ATTRIB
				; FIELD OF THE CONNECT MESSAGE)
LRLADL==:(1B15)			;INDICATES THAT THIS LINE POSSESES AN AUTO-
				; DIALER (ALSO SET BY CONNECT MESSAGE)
LRL741==:(1B16)			;INDICATES THAT THIS IS A 2741 LINE.
LRLTIW==:(1B17)			;SAYS THAT WE ARE IN TTY INPUT WAIT.  (I.E. WE
				; SHOULD UNLOCK THE 2741'S KEYBOARD)
LRRSHC==:1B18			;SAYS THAT THE LINE AT THE OTHER END HAS
				;  "SET HOST CAPABILITY".  (I.E. IT CAN
				;  RESPOND TO DISCONNECT MESSAGES).  NOT
				;  SET FOR DC72 LINES. SET FOR ALL OTHERS.

LRLCLR==:LRLDSR!LRLDTR!LRLTIW	;BITS THAT ARE OFF ON "VIRGIN" LINES
>;END OF IFN FTNET


;DEFINITIONS FOR SUPPORT OF RSX-20F TERMINALS

IFN FTKL10,<		;TTD'S ONLY ON A KL
LDBTTD::!0		;LINE INFO FOR -20F LINES
;	740000		;REMEMBERED TRANSMIT SPEED
;	036000		;REMEMBERED RECEIVE SPEED
LTLXOF==:1000		;SENT XOFF TO -20F
LTLRBS==:400		;REMOTE BIT SENT FOR -20F DATASETS
LTLCTO==:200		;NEED TO SEND FLUSH OUTPUT TO -20F
LTLAXF==:100		;AUTO-XOFF ENABLE SENT TO -20F
LTLACK==:40		;LINE WAITING FOR AN ACK
>;END FTKL10
IFN FTMIC,<		;IF MIC INCLUDED
;WORD FOR MIC TO USE
LDBMIC::0

;0	SET IF SOME BIT 1-14 IS SET
;1	SET IF A ↑C HAS BEEN TYPED
;2	SET IF OPERATOR CHAR SEEN IN COLUMN1
;3	SET IF ERROR CHAR SEEN IN COLUMN 1
;4	SET IF A ↑P HAS BEEN TYPED
;5	SET IF A ↑B HAS BEEN TYPED
;6	SILENCE THIS LINE
;7	LINE IN MONITOR MODE
;		NOT SET IN LDBMIC BUT IS SET ON A MICGET
;8	LINE IN USER MODE AND IN TI WAIT OR IN MONITOR MODE
;	AND CAN ACCEPT A COMMAND
;		NOT SET IN LDBMIC BUT IS SET ON A MICGET
;9	LINE IS IN COLUMN 1 ON OUTPUT
;	USED FOR ERROR AND OPERATOR CHECKING
;10	SET IF A ↑A HAS BEEN TYPED (ABORT)
;11	SET IF TERMINAL OUTPUT IS AVAILABLE
;15-21	ASCII CHAR TO BE TREATED AS OPERATOR CHAR
;		SET IN RESPONSE TO OPERATOR COMMAND
;		CLEARED IN RESPONSE TO NOOPERATOR COMMAND
;		OR ON LOGOUT
;22-28	ASCII CHAR TO BE TREATED AS ERROR CHAR
;		SET IN RESPONSE TO ERROR COMMAND
;		CLEARED IN RESPONSE TO NOERROR COMMAND
;		OR ON LOGOUT
;29-35	MIC MASTER JOB NUMBER - ENABLES MORE THAN ONE MIC TO RUN

LDLCHK==400000		;SOMETHING EXCITING HAPPENED
LDLMCC==200000		;↑C TYPED
LDLOPC==100000		;OPERATOR CHARACTER SEEN IN COLUMN 1
LDLERC==40000		;ERROR CHARACTER SEEN IN COLUMN 1
LDLMCP==20000		;↑P TYPED
LDLMCB==:10000		;↑B TYPED
LDLSIL==4000		;THIS LINE IS .SILENCE'D
LDLMMM==2000		;LINE IN MONITOR MODE (MICGET)
LDLMTI==1000		;LINE IN INPUT READY STATE
LDLCL1==400		;CARRIAGE IS IN COLUMN 1
LDLMCA==200		;↑A TYPED
LDLRSP==100		;ERROR RESPONSE
LDLRSY==:40		;RESPONSE CODE SYNC
IFN FTMLOG,<
LDLLOG==20		;MIC IS LOGGING

LDBLOT::0		;LOG TAKER,,COUNT OF CHARS TO LOG
LDBLOC::0		;COUNT OF CHARACTERS TO LOG
> ;END OF FTMLOG CONDITIONAL
> ;END OF MIC CONDITIONAL
DEPHASE

LDBLEN==:.-SCNLDB		;SIZE OF DATA BLOCK FOR A LINE
;DISPATCH TABLE FOR PTYS AND CTYS.

IFN FTKI10!FTKS10,<
CTYDSP::JRST	CTYTYO		;TYPEOUT
	POPJ	P,0		;MODEM CONTROL
	POPJ	P,0		;ONCE A SECOND
	POPJ	P,0		;INITIALIZATION
	POPJ	P,0		;CHANGE HARDWARE PARMS
	POPJ	P,		;LINE PARM CONTROL
	POPJ	P,		;SET ELEMENT
	POPJ	P,		;REMOTE STUFF
	JRST	CPOPJ1##	;IS LINE UP?
>

ERRDSP::POPJ	P,0		;TYPEOUT
	POPJ	P,0		;MODEM CONTROL
	POPJ	P,0		;ONCE A SECOND
	POPJ	P,0		;INITIALIZATION
	POPJ	P,0		;CHANGE HARDWARE PARMS
	POPJ	P,		;LINE PARM CONTROL
	POPJ	P,		;SET ELEMENT
	POPJ	P,		;REMOTE STUFF
	JRST	CPOPJ1##	;IS LINE UP?

;LINE SPEED MNEMONICS

LS0000==:0	;ZERO BAUD
LS0050==:1	;50 BAUD
LS0075==:2	;75 BAUD
LS0110==:3	;110 BAUD
LS0134==:4	;134.5 BAUD
LS0150==:5	;150 BAUD
LS0200==:6	;200 BAUD
LS0300==:7	;300 BAUD
LS0600==:10	;600 BAUD
LS1200==:11	;1200 BAUD
LS1800==:12	;1800 BAUD
LS2400==:13	;2400 BAUD
LS4800==:14	;4800 BAUD
LS9600==:15	;9600 BAUD

;DATA POINTERS INTO LDB

LDPLCH:	POINT	8,LDBTTW(U),7		;POINTER TO LAST CHAR COMCON READ
LDPFCT:	POINT	8,LDBTTW(U),20		;POINTER TO FILLER REPEAT COUNTER
LDPTTT::POINT	7,LDBTTW(U),35
LDPCPU::POINT	3,LDBBYT(U),24
LDPFLC::POINT	2,LDBBYT(U),2		;POINTER TO INDEX OF FILLER CLASSES

IFN FTCIMP,<				;[arpa]
LDPLNO::POINT	8,LDBDCH(U),35		;[arpa] POINTER TO HARDWARE LINE NUMBER
>					;[arpa]  RESPECTS STOLEN BIT FOR LDRIMP
IFE FTCIMP,<				;[arpa]
LDPLNO::POINT	9,LDBDCH(U),35		;POINTER TO HARDWARE LINE NUMBER
>					;[arpa]

LDPSVC:	POINT	9,LDBBYT(U),14		;POINTER TO SAVED CHARACTER
					;TO BE USED AFTER FILLERS SENT
LDPTIM:	POINT	5,LDBBYT(U),19		;POINTER TO FIELD WHICH TIMES OUT
					; IMAGE MODE INPUT
IFN FTHDPX!FTTRACK,<
LDPECK::POINT	8,LDBBYT(U),35		;POINTER TO LAST CHARACTER SENT, FOR
					; ECHO CHECK ON HDX LINE
>
LDPDEM::POINT	1,LDBBYT(U),↑L<L1RDEM>	;POINTER TO L1RDEM BIT
LDPFRM:	POINT	1,LDBDCH(U),↑L<(LDLFRM)>;POINTER TO HARDWARE FORM FEED BIT
LDPTAB:	POINT	1,LDBDCH(U),↑L<(LDLTAB)>;POINTER TO HARDWARE TABS BIT
LDPLCT:	POINT	1,LDBDCH(U),↑L<(LDLLCT)>;POINTER TO LOWER CASE BIT
LDPIMI::POINT	1,LDBDCH(U),↑L<(LDLIMI)>;POINTER TO IMAGE MODE FLAG
LDPPIM::POINT	1,LDBDCH(U),↑L<(LDLPIM)>;POINTER TO PIM MODE FLAG
LDPFCS::POINT	1,LDBDCH(U),↑L<(LDLFCS)>;POINTER TO FULL CHAR SET FLAG
LDPBKA::POINT	1,LDBDCH(U),↑L<(LDLBKA)>;POINTER TO BREAK ON ALL CHARS FLAG
LDPALT:	POINT	1,LDBPAG(U),↑L<(LPLALT)>;POINTER TO ALTMODE CONVERSION BIT
LDPDIS:	POINT	1,LDBPAG(U),↑L<(LPLDIS)>;POINTER TO DISPLAY TERMINAL BIT
LDPOSU:	POINT	1,LDBDCH(U),↑L<LDROSU>	;POINTER TO OUTPUT SUPPRESSION (↑O) BIT
PRPOS:	POINT	8,LDBTTW(U),28		;POINTER TO HORIZONTAL POSITION AFTER PROMPT
POHPOS:	POINT	3,LDBBYT(U),5		;POINTER TO LOW 3 BITS OF HPOS
					; BEFORE A TAB (FOR TAB SIMULATION)
LNPVRG:	POINT	13,LINTAB##(T1),12	;POINTER TO LOW CORE COPY OF BITS FOR RESTART
LDPVR1:	POINT	6,LDBDCH(U),17		;POINTER TO STORE SOME OF ABOVE BITS
LDPVR2:	POINT	5,LDBDCH(U),24		;POINTER TO STORE SOME MORE OF ABOVE.
LDPCMX::POINT	4,LDBDDB(U),12		;POINTER TO INDEX OF FORCED COMMANDS
IFN FTTRACK,<
LDPRCS:	POINT	8,LDBBY2(U),35		;POINTER TO RECEIVED CHARACTER
					; SAVED FOR WATCHING IN LIGHTS.
>
LDPWID::POINT	8,LDBBY2(U),27		;POINTER TO WIDTH OF TERMINAL CARRIAGE
IFN FTMODM,<
LDPDSC::POINT	9,LDBBY2(U),17		;POINTER TO DATASET CONTROL TABLE INDEX
>
LDPPSZ::POINT	6,LDBPAG(U),29		;PAGE SIZE (# OF LINES)
LDPPCT:	POINT	6,LDBPAG(U),35		;PAGE COUNTER
LDPPFF:	POINT	6,LDBPAG(U),23		;L.F. COUNTER FOR SIMULATION OF V.T. & F.F.
LDPDEB::POINT	2,LDBBYT(U),26		;POINTER TO DEFERRED ECHO BITS
IFN <FTCAFE!FTKS10!FTNET>,<
LDPSPD::POINT	8,LDBISR(U),8		;BOTH SPEEDS
>
LDPRTC::POINT	1,LDBISR(U),11		;↑R, ↑T COMPATIBILITY
LDPRSP::POINT	4,LDBISR(U),8		;RECEIVE SPEED
LDPTSP::POINT	4,LDBISR(U),4		;TRANSMIT SPEED
LDPAPL::POINT	1,LDBISR(U),9		;APL MODE BIT
LDPDBK::POINT	1,LDBISR(U),10		;DEBREAK FEATURE EXISTS
LDP274::POINT	1,LDBDCH(U),22		;LINE IS A 2741
LDPTDY::POINT	1,LDBISR(U),12		;DO NOT EXPAND OUTPUT
LDPACR::POINT	8,LDBPAG(U),17		;AUTO CRLF POINT


IFN FTNET,<
;FIELDS IN THE LDBREM AREA.  (USED BY NETWORK LINES)

LDPSTS::POINT	16,LDBREM+0(U),35	;CONTAINS THE LAST DAP STATUS MESSAGE
LDPSLA::POINT	13,LDBREM+2(U),12	;CONTAINS OUR SOURCE LINK ADDRESS
LDPDLA::POINT	13,LDBREM+2(U),25	;CONTAINS OUR DESTINATION LINK ADDRESS
LDPRLN::POINT	10,LDBREM+2(U),35	;LINE NUMBER AT REMOTE STATION
LDPELE::POINT	4,LDBREM+3(U),3		;2741 ELEMENT NUMBER
LDPDRQ::POINT	8,LDBREM+3(U),11	;NUMBER OF DATA-REQUESTS FROM REMOTE
LDPEPM::POINT	8,LDBREM+3(U),19	;SERIAL NUMBER OF LAST EPM FROM REMOTE
LDPRNN::POINT	16,LDBREM+3(U),35	;NUMBER OF NODE OWNING THIS TTY
LDPRNF::POINT	16,LDBREM+3(F),35	; SAME AS ABOVE, EXCEPT INDEXED BY "F"

LDPCHR::POINT	9,LDBREM+4(U),8		;IF LRLTTO =1, THIS CONTAINS THE NEXT
					; OUTPUT CHARACTER
LDPADT::POINT	9,LDBREM+4(U),17	;AUTO-DISCONNECT TIMER.
LDPJOB::POINT	9,LDBREM+4(U),26	;POINTER TO JOB (ONLY FOR CONNECTS)
LDPDST::POINT	18,LDBVTQ(U),17		;"DELAYED" STATUS FOR VTM
>;END OF IFN FTNET
IFN FTMIC,<
LDP.OP:	POINT	7,LDBMIC(U),21		;OPERATOR CHARACTER
LDP.ER:	POINT	7,LDBMIC(U),28		;ERROR CHARACTER
LDPMJN:	POINT	7,LDBMIC(U),35		;MIC MASTER JOB NUMBER
> ;END IFN FTMIC



;BITS TO BE CLEARED ON A 140 RESTART

LDIDCM:	XWD	ZZL,ZZR			;TO CLEAR BITS IN LDBDCH
	SUBTTL	DATA STRUCTURES -- TTY DEVICE DATA BLOCK (DDB)

;PROTOTYPE SCANNER DDB. REPLICATED BY ONCE. ONE FOR EACH JOB.

	$LOW
TTYLST::			;LABEL FOR FIRST TTY DDB IN CHAIN

SCNDDB::			;GLOBAL LABEL
PHASE 0

	SIXBIT	/TTY0/		;DEVNAM (PHYSICAL NAME)
	XWD	0,STTYBF+1	;DEVCHR. SIZE OF USER BUFFER
	0			;DEVIOS
	XWD	0,SCNDSP	;DEVSER
	XWD	DVTTY+DVIN+DVOUT,<<1←A>+<1←AL>+<1←PIMMOD>+<1←I>>	;DEVMOD
	0			;DEVLOG (LOGICAL NAME)
	0			;DEVBUF
	0			;DEVIAD
	0			;DEVOAD
	0			;DEVSTS
	XWD	.TYTTY,0	;DEVSTA
	0			;DEVXTR
	0			;DEVEVM
	0			;DEVPSI
	0			;DEVESE
	0			;DEVHCW
	707000,,0		;DEVCPU
	0			;DEVJOB
DDBLDB::!0			;LH=FREE
				;RH=DDBLDB LINKS TO THE LDB.
DEPHASE
XP SCNDDS,.-SCNDDB
	$HIGH
BYTCNT:	POINT	12,DEVOAD(F),12

;DATA WITHIN THE DDB

;USE OF DEVIOS

;LEFT HALF
XP TTYOUW,400000	;REMEMBERS THAT IF IN IOW, IT IS FOR OUTPUT, AS
			; OPPOSED TO INPUT. I.E., WHICH INT WAKES JOB
FRCEND==:200000		;IN IMAGE INPUT, FORCE END OF FILE DUE TO TIMING
IOLBKA==100000		;TEMP INTERNAL BIT TO PRESERVE BKA OVER ↑C/CONT

;RIGHT HALF
IFN FTCIMP,<		;[arpa]
CTLSUP==4000		;[arpa] SUPPRESS ECHO OF CTRL CHAR
>			;[arpa]
IOSBKA==1000		;BREAK ON ALL CHARACTERS
IOSTEC==400		;SUPPRESS ECHO OF DOLLAR SIGN ON ALTMOD
IOSNEC==:200		;USER (E.G. LOGIN) SUPPRESSING ECHO
IOSFCS==100		;USER WANTS ALL CHARACTERS.
	SUBTTL	TRANSMIT INTERRUPT ROUTINE

;ENTRY FROM DEVICE-DEPENDENT INTERRUPT SERVICE ROUTINE ON A
; TRANSMIT-DONE INTERRUPT. THE HARDWARE LINE NUMBER IS
; IN AC U.  ENTER AT XMTIN1 IF U IS SETUP TO THE LDB ADDRESS.


XMTINT::MOVE	U,LINTAB##(U)	;GET LINE DATA BLOCK ADDRESS
XMTIN1::MOVSI	T1,L1LOFL
	ANDCAM	T1,LDBOFL(U)
	SKIPGE	LDBDCH(U)	;ARE WE EXPECTING THIS?
	JRST	XMTDMC		;NO, GO UNLOCK KEYBOARD
	PUSHJ	P,XMTCHR	;GET A CHARACTER FROM THE CHUNKS
	  POPJ	P,		;END OF STRING
	MOVSI	T1,LPLIRM	;IRMA BIT
	ANDCAM	T1,LDBPAG(U)	;CLEAR SINCE JUST SENT A CHARACTER
IFN FTHDPX,<
	MOVSI	T1,L2LHDM	;HALF DUPLEX BITS
	ANDCAM	T1,LDBBY2(U)	;CLEAR THEM IN THE LDB
>
	MOVEI	T1,ISRTYP	;FUNCTION DESIRED FROM DEVICE DRIVER
	PJRST	@LDBISR(U)	;GO DO IT

;XMTCHR -- ROUTINE TO RETURN THE NEXT CHARACTER TO SEND FROM
;	   A TERMINAL OUTPUT BUFFER
;
;CALL
;	MOVE	U,LDB ADDRESS
;	PUSHJ	P,XMTCHR
;	  <IDLE CONDITION>
;	<CHARACTER IN T3>

XMTHCH:	MOVE	T1,LDBDCH(U)	;GET SPECIAL BITS FROM LDB
	TRZ	T1,LDRHLF	;BUT CLEAR HALF DUPLEX BIT FOR NOW
	JRST	XMTCH1		;JOIN XMTCHR

XMTCHR::MOVE	T1,LDBDCH(U)	;GET SPECIAL BITS FROM LDB
XMTCH1:	TDNE	T1,[DCHSPC]	;ANY UNUSUAL STATES?
	JRST	XMTSPC		;YES, GO HANDLE SPECIAL CASES
XMTCH2:	SCNOFF			;NO INTERRUPTS WHILE TAKING CHARACTERS
	SOSGE	T4,LDBTOC(U)	;COUNT DOWN LENGTH OF OUTPUT STREAM
	JRST	ZAPBUF		;IF EMPTY STREAM.  GO RESET COUNT
	LDCHKR	T3,LDBTOT(U)	;TAKE NEXT CHARACTER FROM STREAM
XMTCH3:	SCNON			;HAVE CHARACTER, ALLOW OTHERS TO ACCESS
	CAIN	T4,↑D50		;HAVE WE REACHED THE WAKE THRESHOLD?
	PUSHJ	P,XMTWAK	;YES, GO WAKE JOB IF WAITING
IFN	FTMIC,<
	MOVE	T4,LDBMIC(U)	;GET MIC BITS
	TLNE	T4,LDLSIL	;LINE SILENCED
	JRST	XMTCHR		;YES, EAT THE CHARACTER
>
XMTCH4:	TRNE	T3,400		;IS THIS AN IMAGE MODE CHARACTER?
	JRST	XMTCN6		;YES, COUNT IT AND RETURN
	ANDI	T3,177		;CLEAR POSSIBLE PARITY BIT
	SKIPGE	T1,CHTABL(T3)	;GET SPECIAL BITS, TEST FOR UNUSUAL CHAR
	JRST	XMTSPO		;THIS MAY REQUIRE FILL OR BLANK SUPPRESS
	AOSG	LDBHPS(U)	;INCREMENT HORIZONTAL POSITION
	JRST	XMTCN5		;RETURN IF NOT END OF CARRIAGE
	PUSHJ	P,PTBTCH##	;CHECK FOR REGULAR PTY
	  JRST	XMTCN5		;NO FREE CRLF FOR LOG FILES
	MOVE	T2,LDBDCH(U)	;GET CHARACTERISTICS WORD
	TLNE	T2,LDLNFC	;USER WANT FREE <CR><LF>?
	JRST	XMTCN5		;NO, JUST SEND THE CHARACTER
	TLZ	T1,CHALT!CHUAE!CHCRE  ;OUTPUT CHARACTERS GO STRAIGHT
	PUSHJ	P,SETCRF	;YES, GO SETUP A CRLF FILLER
	  JRST	XMTFIL		; AND SEND THE FILLER INSTEAD
	JRST	XMTCN5		;GO SEND THE CHARACTER AFTER ALL!
;COUNT UP THE CHARACTERS PHYSICALLY OUTPUT AND RETURN

XMTCNT:
IFN FTTVP,<
	CAIN	T3,12		;LINEFEED?
	PUSHJ	P,INCPCT	;DUMP PAGE COUNTER
>
XMTCN4:
IFN FTCIMP,<			;[arpa]
	SKIPE	LDBIMP(U)	;[arpa] IF AN IMP, DON'T TRASH IMAGE BIT YET
	  JRST	XMTCN6		;[arpa] JUST CHECK FOR TELNET CONTROL
>				;[arpa]
	ANDI	T3,777		;WE MAY HAVE TRASHED PARITY, SO
	LDB	T1,[POINT 7,T3,35] ;GET THE LOW ORDER 7 BITS
	MOVE	T1,CHTABL(T1)	;GET THE CHAR'S BITS
	TRNE	T3,400		;IS THIS IMAGE MODE FILL?
	  JRST	XMTCN6		;YES, DON'T MESS WITH PARITY
XMTCN5:	ANDI	T3,177		;CLEAR POSSIBLE BAD PARITY
	TLNN	T1,CHEPAR	;IF THE CHAR REQUIRES PARITY
	TRO	T3,200		;THEN MAKE THE PARITY EVEN
XMTCN6:
IFN FTCIMP,<			;[arpa]
	TRNE	T3,400		;[arpa] IMAGE BIT SET?
	 SKIPN	LDBIMP(U)	;[arpa] AND XPATCHED?
	  JRST	XMTCNX		;[arpa] NO, LEAVE IMAGE ALONE
	ANDI	T3,377		;[arpa] GET 8 BITS OF CHAR
	TRNE	T3,200		;[arpa] TELNET CONTROL?
	  JRST	XMTCHR		;[arpa] YES, NO ECHO
XMTCNX:				;[arpa]
>				;[arpa]
IFN FTRSP!FTACCT,<		;IF COUNTING CHARACTERS, THEN
	AOS	LDBOCT(U)	;COUNT CHARACTERS OUTPUT THIS LINE
	AOS	%SCNXI		;AND TOTAL CHARACTERS OUTPUT BY SYSTEM
> ;END IFN FTRSP!FTACCT
	PJRST	CPOPJ1##	;RETURN THE CHARACTER



;HERE FOR UNUSUAL CHARACTER ON OUTPUT

XMTSPO:	HLL	U,LDBDCH(U)	;SETUP LEFT HALF OF U WITH BITS
	TLNN	T1,CHEPAR	;NEED A PARITY BIT?
	TRO	T3,200		;YES, ADD IT
IFN FTTBLK,<
	MOVSI	T2,LPLBLK
	TDNE	T2,LDBPAG(U)
	PUSHJ	P,BLSUPO	;CHECK FOR TERMINAL NO BLANKS
>
	PUSHJ	P,ADJHP
	PUSHJ	P,SETFLO	;SETUP FILLERS IF ANY NEEDED
	  JRST	XMTFIL		;FILLS NEEDED, GO SEND THEM FIRST
IFN FTTVP,<
	CAIN	T3,12		;IF LINE FEED
	PUSHJ	P,INCPCT	; INCREMENT PAGE COUNT
>
	JRST	XMTCN6		;NONE NEEDED, JUST RETURN IT
;HERE WHEN A SPECIAL CONDITION BIT IS SET IN THE LDB.  THESE BITS
;ARE PLACED IN LDBDCH IN SUCH A WAY THAT A JFFO INSTRUCTION CAN
;BE USED TO FIND THE CONDITION THAT NEEDS ATTENTION FIRST.

XMTSPC:	HLL	U,LDBDCH(U)	;CARRY LEFT HALF OF LDBDCH IN U 
	AND	T1,[LDLIDL!LDLSTP!LDLSSO!LDLFCP!LDLPIM!LDLMIC,,0]
	JFFO	T1,XMTSP1	;GET FIRST FLAG SET
	MOVE	T1,LDBDCH(U)	;REFRESH BITS
	JRST	XMTHDX

XMTSP1:	JRST	@[EXP XMTCIS,XMTSTP,XMTSSO,XMTFLC,XMTPIM,XMTMIC](T2)

XMTSTP:
XMTSSO:	SKIPN	LDBFLP(U)	;KROCK - ALLOW FILLER POINTER TO FINISH
	JRST	XMTIDL		;NO FILLER, NO OUTPUT
				;FALL INTO XMTFLC

XMTFLC:	SCNOFF			;NO INTERRUPTS WHILE TRY TO CLEAR FPC
	SKIPE	LDBXNP(U)	;XON CLASS POINTER?
	JRST	XMTXOF		;YES, GO SEND NOW
	SKIPE	LDBFLP(U)	;FILLER POINTER SETUP?
	JRST	[SCNON
		 JRST	XMTFI0]	;YES, GO SEND FILLER
	MOVSI	T1,LDLFCP	;SET TO CLEAR
	ANDCAM	T1,LDBDCH(U)	;FORCED CHARACTER PENDING
	SCNON
	JRST	XMTCHR		;NOW SEE WHAT NEEDS TO BE DONE

;HERE IF LINE IS IDLE.  CLEAR IDLE STATE AND TRY TO RETURN
; A CHARACTER.  XMTIDL WILL RESET IDLE IF NOTHING TO SEND.

XMTCIS:	MOVSI	T1,LDLIDL
	ANDCAM	T1,LDBDCH(U)	;MARK LINE AS BUSY
	PJRST	XMTCHR		;TRY TO RETURN A CHARACTER
;FALL THROUGH TO HERE TO IDLE A LINE.

XMTIDL:	HLL	U,LDBDCH(U)
	MOVSI	T1,LDLIDL	;LINE IS IDLE BIT
	IORM	T1,LDBDCH(U)	; SET IN LDB
	MOVSI	T1,LPLIRM	;IRMA BIT
	ANDCAM	T1,LDBPAG(U)	; CLEAR
IFN FTCIMP,<			;[arpa]
	MOVEI	T1,LDRIMP	;[arpa] IMPISH?
	TDNE	T1,LDBDCH(U)	;[arpa] ....
	  PUSHJ	P,XMTQIT##	;[arpa] FINISH UP OUTPUT IMP MESSAGE
>				;[arpa]
IFN FTHDPX,<
	MOVSI	T1,L2LHDM	;CLEAR HALF DUPLEX FLAGS TOO
	ANDCAM	T1,LDBBY2(U)	; ..
>
	HRRZ	F,LDBDDB(U)	;ADDRESS OF LINKED DDB
	PUSH	P,J		;SAVE J
	JUMPE	F,XMTPSI	;JUMP IF NO DDB
	LDB	J,PJOBN##	;GET JOB NUMBER
	MOVE	T1,JBTSTS##(J)	;GET JOB STATUS
	TRNE	T1,JS.NTO	;HIBERING FOR NON-BLOCKING TTY OUTPUT?
	PUSHJ	P,WAKEJB##	;YES--WAKE HIM UP
XMTPSI:	POP	P,J		;RESTORE J

XMTDMC:	HRRZ	F,LDBDDB(U)	;IF NO DDB ALL DONE
	JUMPE	F,CPOPJ##	;IF NO DDB.
	MOVE	S,DEVIOS(F)	;IO STATUS
IFN FTCAFE&FT2741!FTNET,<
	SKIPGE	LDBDDB(U)	;ANY COMMAND?
	JRST	XMTWAK		;YES--WAIT FOR IT
	TLNE	U,LDLCOM	;AT COMMAND LEVEL?
	PUSHJ	P,UNLKBD	;YES--UNLOCK KEYBOARD
	JUMPGE	S,XMTWAK	;IF WAITING FOR OUTPUT
	TLNE	S,IOW		;WAITING FOR IO?
	PUSHJ	P,UNLKBD	;YES, THEREFORE INPUT MUST
				; UNLOCK 2741 KEYBOARD
>
XMTWAK:
IFN FTNET,<
	SKIPGE	LDBREM(U)	;IF THIS IS A VTM LINE
	PJRST	VTMENQ##	;  QUEUE THE LINE SO WE SEND MORE DATA-REQUESTS
>
IFN FTMIC,<
	SKIPN	T1,LDBMIC(U)	;CONTROLLED BY MIC?
	JRST	XMTWK1		;IF NOT
IFN FTMLOG,<
	TLNE	T1,LDLLOG	;LOGGING
	PUSHJ	P,MLOGOF	;TIDY UP
> ;END IFN FTMLOG
	PUSHJ	P,MICWAK	;WAKE MIC
> ;END IFN FTMIC
XMTWK1:
IFN FTCIMP,<			;[arpa]
	SKIPE	F,LDBIMP(U)	;[arpa] CROSSPATCHED IMP?
	  PUSHJ	P,RQTIIO##	;[arpa] YES - REQUEST IMP/TTY PROCESSING
>				;[arpa]
	HRRZ	F,LDBDDB(U)
	JUMPE	F,CPOPJ##
	MOVE	S,DEVIOS(F)
	TLNE	S,IOW		;IO WAIT?
	JUMPL	S,TTWAKE	;IF OUTPUT, GO WAKE JOB
	POPJ	P,		;IF INPUT, RETURN
;PACKED IMAGE MODE (PIM) TRANSMIT INTERRUPT.

XMTPIM:	SCNOFF
	SOSGE	T4,LDBTOC(U)	;COUNT DOWN
	PJRST	ZAPOU1		;IF EXHAUSTED
	LDCHKR	T3,LDBTOT(U)	;TAKE A CHARACTER, RETURN STALE CHUNKS
	SCNON			;ALLOW INTERRUPTS
	CAIN	T4,↑D50		;IF LESS THAN 50. CHARS LEFT 
	PUSHJ	P,XMTWAK	;WAKE UP THE ATTATCHED JOB
	JRST	XMTCN6		;COUNT AND RETURN THE CHARACTER

;HERE WHEN THE OUTPUT STREAM COUNT IS EXHAUSTED.  RESET IT TO ZERO
;AND SET THE LINE IDLE.  COME HERE ONLY WITH SCANNER INTERLOCK SET.

ZAPOU1:	SETZM	LDBTOC(U)	;COUNT IS PROBABLY NEGATIVE NOW
	MOVE	T2,LDBTOT(U)	;$MAKE SURE PUTTER MATCHES TAKER
	CAME	T2,LDBTOP(U)	;$MAKE SURE BOTH POINTERS MATCH
	PUSHJ	P,RCCSTP	;$NO, DIE NOW
	SCNON			;ALLOW INTERRUPTS AGAIN
	PJRST	XMTIDL		;IDLE THE LINE


;ROUTINE TO ALLOW SCANNER INTERRUPTS AGAIN AND SKIP RETURN

SONPJ1::AOS	0(P)		;SKIP RETURN

SONPPJ::SCNON			;ALLOW SCANNER INTERRUPTS
	POPJ	P,		;AND RETURN
;HERE ON A TRANSMIT DONE INTERRUPT WHEN LDBMIC IS NON-ZERO

XMTMIC:
IFN FTMIC,<			;IF MIC
IFN FTMLOG,<
	MOVE	T2,LDBMIC(U)
	TLNE	T2,LDLLOG	;HAS HE ASKED FOR LOG
	SKIPE	LDBLOT(U)	;HAS HE GOT A LOG TAKER
	JRST	MICLG3
	MOVE	T2,LDBTOT(U)	;MAKE COPY OF TAKER
	MOVEM	T2,LDBLOT(U)
MICLG3:
> ;END OF FTMLOG CONDITIONAL
	PUSHJ	P,HPOS		;GET HORZONTAL POSITION ON LINE
	JUMPN	T2,XMTOK	;IN COLUMN 1?
	SKIPE	T2,LDBMIC(U)	;IS HE RUNNING MIC OR
	TLNN	T2,LDLRSP!LDLRSY	;WANTS RESPONSE FEATURE
	JRST	XMTOK1		;NO - MUST NOT INTERFERE
	TLNE	T2,LDLERC	;HAS HE HAD ERROR?
	TLNE	T2,LDLMCC	;AND NOT ↑C
	JRST	XMTOK1		;NO - IGNORE
	SKIPN	LDBTOC(U)	;IS THERE A CHARACTER WAITING?
	JRST	XMTOK1		;NO, IGNORE
	MOVE	T4,LDBTOT(U)	;COPY OF OUTPUT TAKER
	LDCHK	T3,T4		;PREVIEW NEXT CHARACTER
	LDB	T2,LDP.ER	;GET ERROR CHAR
	JUMPE	T2,XMTOK	;MUST BE ONE
	ANDI	T3,177		;JUST 7 BITS
	CAIE	T3,"?"		;IS IT A "?"
	CAMN	T3,T2		; OR THE ERROR CHARACTER
	CAIA			;YES, HANDLE MIC'S RESPONSE
	JRST	XMTOK		;NO IGNORE
	MOVSI	T2,LDLRSY!LDLCHK	;SET THE SYNC
	IORB	T2,LDBMIC(U)
	TLNN	T2,LDLRSP	;BEEN THIS WAY BEFORE
	JRST	XMTECH		;YES JUST DO ECHOING
	HRRZ	F,LDBDDB(U)
	JUMPE	F,XMTECH	;NO ATTACHED DDB
	MOVE	S,DEVIOS(F)
	TLNN	S,IOW		;IN IO WAIT?
	JRST	XMTECH		;NO FORGET IT
	MOVSI	T2,LDLRSP
	ANDCAM	T2,LDBMIC(U)	;SAY SYNC
	PUSHJ	P,MICWAK
	JRST	XMTECH		;AND PUT THE PLUG IN

XMTOK:	MOVE	T2,LDBMIC(U)	;GET MIC BITS
XMTOK1:	TLNE	T2,LDLRSY	;WAITING FOR MIC TO TAKE RESPONCE
	JRST	XMTECH		;YES, KEEP THE PLUG IN

IFN FTMLOG,<
	SKIPN	LDBLOT(U)	;ARE WE LOGGING THIS?
	JRST	XMTCH2		;NO, GO TAKE CHARACTER NORMALLY
	SCNOFF			;NO INTERRUPTS
	SOSGE	LDBTOC(U)	;DECREMENT COUNT OF CHARACTERS AND TEST
	JRST	ZAPBUF		;IF OUTPUT STREAM NOW EMPTY
	LDCHK	T3,LDBTOT(U)	;TAKE A CHARACTER OUT OF THE STREAM
	AOS	LDBLOC(U)	;COUNT UP THE NUMBER TO BE LOGGED
	JRST	XMTCH3		; AND JOIN PROCESSING
> ;END IFN FTMLOG
> ;END OF IF MIC

;ENTER HERE WITH SCNOFF TO CLEAR LDBTOC AND CHECK FOR ECHO

ZAPBUF:	SETZM	LDBTOC(U)	;ZERO COUNT
	MOVE	T1,LDBTOP(U)	;GET PUTTER
	CAME	T1,LDBTOT(U)	;MUST MATCH TAKER
	PUSHJ	P,RCCSTP	; OOPS, SOMETHING IS WRONG
	SCNON			;ALLOW INTERRUPTS
IFN FTNET,<
	SKIPGE	LDBREM(U)	;IF THIS IS A VTM LINE,
	PUSHJ	P,VTMENQ##	;  WE MUST BE SURE TO SEND DATA-REQUESTS
>				;  NOW THAT WE'RE OUT OF DATA.
	JRST	XMTECH		;LOOK FOR SOMETHING TO ECHO
;HERE ON A TRANSMIT DONE INTERRUPT WHEN LDBXNP IS NON-ZERO.
;LDBXNP IS A NINE-BIT BYTE POINTER TO FORCED CHARACTERS SUCH AS
; XOFF AND BELL.

XMTXOF:	SCNON			;ALLOW INTERRUPTS
	ILDB	T3,LDBXNP(U)	;GET A CHARACTER.
	JUMPN	T3,XMTCNT	;COUNT THE CHARACTER AND RETURN
	SETZM	LDBXNP(U)	;REACHED END. CLEAR POINTER
	SKIPN	LDBFLP(U)	;IS THERE A FILLER POINTER?
	JRST	XMTCHR		;NO, SEE IF ANY OUTPUT STREAM
				;YES, FALL INTO XMTFIL

;HERE ON A TRANSMIT-DONE INTERRUPT WHEN LDBFLP IS NON-ZERO.
;LDBFLP IS A NINE-BIT BYTE POINTER TO FILLER CHARACTERS, OR
; TO FREE CRLF'S OR TAB SIMULATIONS.

XMTFIL:
XMTFI0:	SCNOFF			;NO INTERUPTS FOR A FEW INSTRUCTIONS
	HLL	U,LDBDCH(U)	;REFRESH LEFT HALF OF U
	ILDB	T3,LDBFLP(U)	;GET A FILLER CHARACTER
	JUMPN	T3,XMTFI1	;IF NOT AT END, SEND IT AND DISMISS
	LDB	T1,LDPFCT	;FILL REPEAT COUNTER
	JUMPE	T1,XMTFI3	;JUMP IF NO REPEAT COUNT
	LDB	T3,LDPSVC	;SAVED CHARACTER
	SCNON			;OK TO INTERUPT WITH CHARACTER IN T3
	MOVSI	T1,LDLUAW	;CONTROL W BIT
	TDNE	T1,LDBTTW(U)	;PROCESSING CONTROL W?
	JUMPN	T3,[MOVEI T2,1	;YES, JUMP IF HARD COPY TERMINAL
		    PUSHJ P,SETFLP ;STORE DUMMY FILLER POINTER
;		    SETZ T1,	;ZERO SAVED CHARACTER
		    JRST XMTFI4];ECHO CHARACTER AND RETURN
	ANDI	T3,177		;JUST 7 BITS
	TDNE	T1,LDBTTW(U)	;SKIP IF NOT CONTROL W
	SKIPA	T1,CHTABL+"W"-100 ;GET CONTROL W DISPATCH
	MOVE	T1,CHTABL(T3)	;GET CHARACTER DISPATCH
	PUSHJ	P,(T1)		;DISPATCH TO CHARACTER HANDLING ROUTINE
	JRST	XMTFI0		;CHECK FOR MORE FILL
XMTFI3:SCNON
	MOVSI	T1,LPLSAP	;WAITING TO DO A
	TDNE	T1,LDBPAG(U)	;SEND ALL?
	JRST	[SOSGE	SNDCTR##	;COUNT DOWN SEND ALL COUNT
		SETZM	SNDCTR##	;BUT DON'T LET IT GO NEGATIVE!
		ANDCAM	T1,LDBPAG(U)	;YES -- CLEAR BIT
		MOVE	T1,SNDPTR##	;SET UP POINTER
		MOVEM	T1,LDBFLP(U)	;STORE IN LDB
		JRST	XMTFI0]		;TYPE THE STRING
	SETZB	T1,LDBFLP(U)	;END. CLEAR THE BYTE POINTER AND T1
	LDB	T3,LDPSVC	;SEE IF ANY SAVED CHARACTER
	JUMPE	T3,XMTCHR	;IF NOT, RETURN TO XMTCHR AND TRY AGAIN
XMTFI4:	TLNE	U,LDLSSO	;A PAGE BREAK PENDING?
	JRST	[MOVE T2,FLLDMP	;YES, GET DUMMY FILLER POINTER
		 PUSHJ P,SETFLP	;AND SET IT IN THE LDB
		 JRST XMTIDL]	;MARK THE LINE AS IDLE
	DPB	T1,LDPSVC	;CLEAR THE SAVED CHAR BYTE
	TRNE	T3,400		;IF TAB SIMULATION
	JRST	XMTFI2		; WHO KNOWS
	ANDI	T3,177		;JUST CHARACTER
	MOVE	T1,CHTABL(T3)	;CHARACTER DESCRIPTOR BITS
	TRO	T3,200		;SO IT WILL ECHO
	JRST	XMTEC4		;GO TYPE IT

XMTFI2:	MOVE	T1,LDBDCH(U)
	TDNN	T1,[LDLLCP+LDLNEC,,LDRHLF]
	SKIPE	LDBTOC(U)	;WAS THAT CHAR FOR INPUT OR OUTPUT?
	JRST	XMTCH4		;OUTPUT. GO SEND IT WITH FILLERS
	IORI	T3,200		;SET THE "NEED TO ECHO THIS CHAR" BIT
	JRST	XMTEC6		;AND GO ECHO THE POOR THING

XMTFI1:SCNON
	CAIE	T3,FLLFLG	;IS THIS A FLAG OR A CHARACTER?
	PJRST	XMTCNT		;COUNT CHARACTER AND RETURN IT
	PUSHJ	P,SETFLC	;GET CORRECT FILL CLASS
	MOVE	T3,FLLCRP(T2)	;GET RIGHT CRLF POINTER
	MOVEM	T3,LDBFLP(U)	;PLACE IN FILLER POINTER
	PUSHJ	P,SCNBOL	;MAKE SURE AT LOGICAL BOL
	JRST	XMTFI0		;AND GO TYPE FROM IT.
;HERE WHEN BUFFERED AND FILLER OUTPUT DONE, AND LDBECT IS NON-ZERO
;NEED TO ECHO A CHARACTER THAT HAS BEEN TYPED IN.

XMTECH:
IFN FTNET,<
	SKIPGE	LDBREM(U)	;IF THIS IS AN ACTIVE VTM LINE
	JRST	XMTIDL		;  DON'T TRY TO ECHO ANYTHING.
>				;  THE CHUNKS ARE HORRIBLY MESSED UP.
	HLL	U,LDBDCH(U)
	HRRZ	T1,LDBBYT(U)	;GET WORD CONTAINING DEFERRED ECHO BITS
ifn ftcimp,<			;[arpa]
	SKIPE	LDBIMP(U)	;[arpa] Always echo immediately if xpatched
	  JRST	XMTEIP		;[arpa]
>				;[arpa]
	TRNE	T1,L1RDEM	;DEFERRED ECHO MODE SELECTED?
	TRNE	T1,L1RDEL!L1RDEC; HAS AN INPUT REQUEST BEEN MADE YET?
	CAIA			;EITHER INPUT WAIT OR IMMEDIATE ECHO
	JRST	XMTIDL		;DEFERRED AND NOT REQUESTED YET
IFN FTCIMP,<			;[arpa]
XMTEIP:				;[arpa] here to avoid defering echo.
>				;[arpa]
	SCNOFF			;DISALLOW INTERRUPTS
	SOSGE	LDBECC(U)	;ANY LEFT TO ECHO?
	JRST	ZAPECH		;NO, FINISH UP
	LDCHK	T3,LDBECT(U)	;TAKE CHARACTER FROM INPUT, SAVE CHUNKS
	AOS	T2,LDBTIC(U)	;COUNT THE INPUT CHARACTERS
	SCNON			;ALLOW INTERRUPTS
IFN FTRSP!FTACCT,<AOS %SCNEI>	;COUNT CHARACTERS ECHOED
	MOVEI	T4,L1RDEC	;CHARACTER REQUEST BIT
	PUSHJ	P,SPCHEK	;SEE IF IT'S SPECIAL.
	  JRST XMTEC1		;IT'S NOT.
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] don't treat as break if crosspatched
>				;[arpa]
	TLNN	T1,CHBRK	;YES. IS IT A BREAK CHAR?
	JRST	XMTEC1		;NOT A BREAK
	MOVEI	T4,L1RDEC!L1RDEL;GET LINE REQUESTED BIT
	AOS	LDBBKC(U)	;COUNT LINES IN THE LDB
IFN FTRSP!FTACCT,<AOS LDBBCT(U)>;COUNT BREAK CHARACTERS INPUT
XMTEC1:	ANDCAM	T4,LDBBYT(U)	;CLEAR, SINCE WE ECHOED A CHARACTER
	PUSH	P,T1		;SAVE CHARACTER BITS
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] always break if xpatched to an imp.
>				;[arpa]
	TLNE	U,LDLBKA+LDLIMI	;BREAK ON ALL CHARACTERS?
	JRST	[PUSHJ	P,RCVWKQ	;YES, WAKE JOB
	JRST	XMTEC2]		;AVOID EXTRA WAKE IF BREAK TOO
	CAIG	T2,TTIBRK	;ARE THERE OVER 72. OF THEM?
	TLNE	T1,CHBRK	;OR IS IT A BREAK CHARACTER?
	PUSHJ	P,ECHBRK	;YES. WAKE THE JOB, IF ANY
XMTEC2:	POP	P,T1		;RESTORE CHARACTER BITS INTO T1

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

XMTEC3:
IFN FTMIC,<
	SKIPE	T2,LDBMIC(U)	;MIC IN CONTROL OF THIS LINE?
	TLNN	T2,LDLSIL	;YES, IS IT .SILENCED?
	CAIA			;NOT .SILENCED OR NOT MIC
	JRST	XMTCHR		;.SILENCED, EAT THE CHAR
> ;END IFN FTMIC
	TRNN	T3,400		;IMAGE?
	TLNE	U,LDLNEC	;NON-ECHOING?
	JRST	XMTEC6		;YES, LEAVE ALONE
	MOVE	T2,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TDNN	T2,[XWD LDLLCP,LDRHLF]	;LOCAL COPY?
	JRST	XMTEC4		;NO, COUNT UP NORMAL CHARACTER
	MOVEI	T2,L2RXON	;PAPER TAPE?
	TDNE	T2,LDBBY2(U)	;...
	JRST	XMTEC6		;YES.  NO FILLERS, ELSE GARBLE.
XMTEC4:	TLNE	T1,CHSPO	;SPECIAL CHARACTER OF SOME FLAVOR?
	JRST	XMTEC5		;YES, MORE EXTENSIVE HANDLING REQUIRED
	AOSG	LDBHPS(U)	;NORMAL CHARACTER, ECHO ONE CHAR POSITION
	JRST	XMTEC6		;GO DO IT
	SOS	LDBHPS(U)	;UNDO AOSG (ADJHP WILL RE-DO IT)
XMTEC5:
IFN FTTBLK,<
	MOVSI	T2,LPLBLK	;THE SUPPRESS-BLANK-LINES BIT
	TDNE	T2,LDBPAG(U)	;"TTY NO BLANK" SET?
	PUSHJ	P,BLSUPI	;YES, NOTE PASSING <LF>S ET AL
> ;IFN FTTBLK
	PUSHJ	P,ADJHP		;ADJUST CARRIAGE POSITION FOR ECHOED CHARACTER
IFN FTCIMP,<			;[arpa]
	SKIPE	LDBIMP(U)	;[arpa] IF CROSSPATCHED...
	  ANDI	T3,377		;[arpa]  ...CLEAR IMAGE BIT FOR ECHOING.
>				;[arpa]
	PUSHJ	P,SETFLI	;SET FILLERS FOR ECHOING
IFN FTLINK,<			;[link]
	  JRST	[			;[link] needs filler
		 PUSHJ	P,CHKLKF##	;[link] SEND FILLER TO ANY LINKS
		 JRST	XMTFI0		;[link] AND OUTPUT FROM FILL POSITION
		]			;[link]
>
IFE FTLINK,<			;[link]
	  JRST XMTFI0		;OUTPUT FROM FILLER POSITION.
>				;[link]
XMTEC6:
ifn FTCIMP,<	;[arpa] check to see if we REALLY want to echo this
	skipn	ldbimp(u)	;[arpa] cross patched?
	  jrst	XMTNCP		;[arpa] no.  don't check
	move	t1,t3		;[arpa] copy character
	andi	t1,177		;[arpa] JUST the character
	move	t1,chtabl(t1)	;[arpa] get the bits for it.
	TLNE	T1,CHALT	;[arpa] IF ALT OR ↑X SUPPRESS ECHO 
	  jrst	XMTChr		;[arpa] go get next character
XMTNCP:				;[arpa] come here if not cross patched
> ;[arpa] end of ifn FTCIMP

IFN FTMIC,<
	SKIPE	T1,LDBMIC(U)	;RUNNING MIC?
	TLNE	T1,LDLMCB	;IN MIC BREAK?
	CAIA			;IN MIC BREAK, DO NORMAL ECHO CHECKING
	JRST	XMTEC8		;NO, MIC CHARACTERS ALWAYS ECHO
> ;END IFN FTMIC
	MOVE	T1,LDBDCH(U)	;GET LEFT AND RIGHT HALF BITS
	TDNE	T1,[XWD LDLLCP,LDRHLF!LDR2741]	;EITHER TYPE OF LOCAL COPY?
	JRST	XMTCHR		;YES. DO NOT ECHO THE CHARACTER
IFN FTNET,<
	TRNN	T3,600		;IF IMAGE, OR NOT ECHOED BY REMOTE
	JRST	XMTCHR		;IF NOT VTM, DON'T ECHO, IF VTM, MUST ECHO HERE
> ;END IFN FTNET		;ECHO THE CHARACTER NOW
XMTEC8:	TLNN	U,LDLCOM	;CHARACTER ITSELF SHOULD BE ECHOED
	TLNN	U,LDLNEC	;UNLESS USER LEVEL AND HE SAID NO
	JRST	XMTCN4		;RETURN CHARACTER
	JRST	XMTCHR		;NO, STEP TO NEXT CHARACTER
ZAPECH:	SETZM	LDBECC(U)	;FIX UP
	MOVE	T2,LDBTIP(U)	;$MESSED UP
	CAME	T2,LDBECT(U)	;$CHECK POINTERS
	PUSHJ	P,RCCSTP	;$SOMETHING IS WRONG
	SCNON			;ALLOW INTERRUPTS
	JRST	XMTIDL

ECHBRK:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  PJRST RCVWAK		;NO. WAKE JOB IF ANY.
	PJRST	COMSET		;YES. SET COMMAND REQUEST.

RCVWKQ:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  PJRST	RCVWAK		;NO. WAKE JOB.
	POPJ	P,0		;YES. DON'T MAKE COMMAND FOR LDLBKA

IFE FTHDPX,<
XMTHDX==CPOPJ##
>
IFN FTHDPX,<
XMTHDX:	JUMPL	T1,XMTHCH	;IF LINE IS IDLE, JUST TREAT NORMALLY
	MOVSI	T1,L2LHD1	;FLAG THAT XMT DONE HAPPENED
	IORB	T1,LDBBY2(U)	; ..
	TLNN	T1,L2LHD2	;HAS REC INT OCCURRED ALSO?
	POPJ	P,		;RETURN
	JRST	RHDERQ		;YES. GO SEE IF ERROR IN ECHO
>

;ROUTINE TO QUEUE FOR A CHANGE HARDWARE PARAMETER MESSAGE

SETCHP::MOVEI	T1,L1RCHP
	IORM	T1,LDBBYT(U)	;MARK THAT ISRCHP MUST BE CALLED
	PJRST	TOPOKE		;ADD TO QUEUE

CLRIRM::MOVSI	T1,LPLIRM	;IRMA BIT
	ANDCAM	T1,LDBPAG(U)	;CLEAR IN LDB
	POPJ	P,		;RETURN
TOREQ::	MOVSI	T1,LDLIDL
	IORM	T1,LDBDCH(U)
;;	PJRST	TOPOKE

;ROUTINE TO PLACE AN LDB INTO THE START OUTPUT QUEUE.  SCANNED
;AT CLOCK LEVEL ONCE PER TICK.
;CALL
;	MOVEI	U,LDB ADDRESS
;	PUSHJ	P,TOPOKE
;	<RETURN HERE ALWAYS>
;USES T1,T2

TOPOKE::MOVEI	T1,LDRPTY	;PTY BIT
	TDNE	T1,LDBDCH(U)	;IS THIS A PTY?
	PJRST	PTYPE##		;YES, DON'T QUEUE OUTPUT
	MOVSI	T1,LPLPOK	;OUTPUT BEING STARTED BIT
	TDNE	T1,LDBPAG(U)	;CHECK BEFORE WE GET THE INTERLOCK
	POPJ	P,		;  JUST FOR EFFICIENCY'S SAKE
	SCNOFF			;NO INTERRUPTS
	TDNE	T1,LDBPAG(U)	;...
	JRST	SONPPJ		;YES, BY SOMEONE ELSE
	IORM	T1,LDBPAG(U)	;NO.  INDICATE LDB IS GOING INTO THE QUEUE
	HLRZ	T1,LDBQUE(U)	;GET THE QUEUE HEADER ADDRESS
	HLRZ	T2,0(T1)	;LAST ENTRY OF CURRENT QUEUE
	SKIPN	T2		;NON-NULL QUEUE?
	MOVEI	T2,-LDBQUE(T1)	;POINT TO QUEUE HEADER WORD
	HRRM	U,LDBQUE(T2)	;STORE ADDRESS OF ARGUMENT LDB AT END
	HRLM	U,0(T1)		;UPDATE LATEST ENTRY
	HLLZS	LDBQUE(U)	;MAKE SURE LIST TERMINATESS
	JRST	SONPPJ		;ALLOW INTERRUPTS AND RETURN


;ROUTINE TO TAKE AN LDB OUT OF THE 'START OUTPUT' QUEUE
;CALLED FROM DEVICE DRIVERS TO FIND LINES THAT ARE WAITING TO DO OUTPUT.
;CALL
;	MOVE	T1,ADDRESS OF LIST HEADER
;	PUSHJ	P,TOTAKE
;	  <IF EMPTY QUEUE>
;	<LDB ADDRESS IN U>
;
;USES T2.

TOTAKE::SKIPN	0(T1)		;IF QUEUE IS EMPTY NOW
	POPJ	P,		; AVOID INTERLOCK
	SCNOFF
TOTAK1:	MOVSI	T2,LPLPOK	;HAS OUTPUT BEEN STARTED?
	HRRZ	U,0(T1)		;POINT TO FIRST LDB IN LIST
	JUMPE	U,SONPPJ	;IF NONE
	ANDCAM	T2,LDBPAG(U)	;CLEAR 'IN QUEUE' BIT
	HRRZ	T2,LDBQUE(U)	;NEXT LDB IN LIST
	SKIPN	T2		;END OF LIST?
	SETZM	0(T1)		;YES, CLEAR HEADER
	HRRM	T2,0(T1)	;ADVANCE LIST
	SKIPGE	LDBDCH(U)	;IS OUTPUT ALREADY GOING?
	JRST	SONPJ1		;LINE IDLE, GIVE GOOD RETURN
	MOVEI	T2,L1RCHP
	TDNN	T2,LDBBYT(U)	;NEED TO SEND CHANGE PARAMETER MESSAGE?
	JRST	TOTAK1		;NO, SKIP TO NEXT
	JRST	SONPJ1		;YES, RETURN THE LINE
	SUBTTL	RECEIVE INTERRUPT ROUTINE

;HERE FROM DEVICE-DEPENDENT INTERRUPT ROUTINE ON A RECEIVE INTERRUPT.
;AT THIS POINT, T3(28-35) HAS RECEIVED CHARACTER, U HAS PHYSICAL LINE #
;AS INDEX INTO LINTAB

RECINT::MOVE	U,LINTAB##(U)	;LOAD LDB ADDRESS
IFN FTCIMP,<			;[arpa]	
	SKIPE	LDBIMP(U)	;[arpa] IF XPATCHED...
	  ANDI	T3,377		;[arpa] ... USE ONLY 8 BITS OF CHARACTER

RecImp::	;[arpa] come here to handle stuff coming over the IMP
>;[arpa]
RECPTY:	MOVEI	T2,L1RMIF	;MIC INTERLOCK FLAG
	SCNOFF			;LOCK OTHER CPU
	TDNE	T2,LDBBYT(U)	;IS MIC TYPING ON THIS LINE?
	JRST	SONPPJ		;YES, IGNORE CHAR
	IORM	T2,LDBBYT(U)	;SET THE INTERLOCK BIT
	SCNON			;ALLOW INTERRUPTS
	PUSHJ	P,RECINU	;PROCESS THE INTERRUPT
	MOVEI	T2,L1RMIF	;GET THIS BIT AGAIN
	ANDCAM	T2,LDBBYT(U)	;CLEAR INTERLOCK
IFN FTRSP!FTACCT,<		;IF COUNTING CHARACTERS
	AOS	LDBICT(U)	;COUNT INPUT CHARACTERS THIS LINE
	AOS	%SCNRI		;AND INPUT CHARACTERS FOR THE SYSTEM
> ;END IFN FTRSP!FTACCT
	POPJ	P,		; AND DISMISS THE INTERRUPT

RECINU:
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] LEAVE IMAGE BIT ALONE IF XPATCHED
>				;[arpa]
	ANDI	T3,377		;JUST 8 BITS OF CHARACTER.
				; CLEAR ANY DEVICE DEPENDENT BITS
IFN FTNET,<			;IF NETWORK
	SKIPGE	LDBREM(U)	;IF THIS IS AN ACTIVE VTM LINE,
	JRST	VTMREC##	;  GO HANDLE NVT CHARS SPECIAL
>
	MOVSI	T1,L1LOFL	;PUT TERMINAL ON LINE
	ANDCAM	T1,LDBOFL(U)	;SINCE SOMEONE IS THERE
IFN FTMODM,<
	MOVE	T1,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TRNN	T1,LDRREM	;IS IT A NETWORK LINE?
	TRNN	T1,LDRDSD	;IS IT A DATASET LINE?
	  JRST	RECINN		;NO.  PROCESS CHARACTER
	LDB	T1,LDPDSC	;GET DATASET TABLE INDEX
	MOVE	T1,DSCTAB##(T1)	;GET DATASET DATA
	TLNE	T1,DSCBLI	;WANT TO IGNORE INTERRUPTS?
	  POPJ	P,		;YES,
RECINN:
> ;END OF IFN FTMODM
	MOVEI	T1,ST.NRT	;THE STAND ALONE (NO REMOTE) BIT
	TDNE	T1,STATES##	;IS THE SYSTEM STAND ALONE?
	JRST	[HRR	T1,LDBDCH(U)	;YES, GET CHARACTERISTICS
		TRNN	T1,LDRDSR	;IS THE TERMINAL REMOTE/DATASET?
		JRST	RECIN0		;NO, LOCAL, ALLOW IT
		HRRZ	T1,LDBDDB(U)	;REMOTE, BUT IS IT ALREADY IN USE?
		JUMPN	T1,RECIN0	;YES, ALLOW IT TO CONTINUE TO WORK
		JRST	BEATIT]		;NO, DUMP IT

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

RECIN0:
IFN FTTRACK,<DPB T3,LDPRCS>	;SAVE RECEIVED CHARACTER FOR DEBUG
IFN FTHDPX,<
	MOVE	T1,LDBDCH(U)	;SEE IF IT IS HALF DUPLEX
	TRNE	T1,LDRHLF	; ..
	JRST	RECHDX		;YES. SPECIAL HANDLING
> ;END IFN FTHDPX
RECIN1:	HLL	U,LDBDCH(U)	;CARRY DEVICE BITS IN LH.
	TLNE	U,LDLPIM	;PIM MODE?
	JRST	REPIM		;YES, GO TO PIM CODE
	SKIPG	TTFREN##	;ANY SPACE FOR CHARACTERS?
	JRST	RCHLT1		;NO. SHUT IT DOWN.
	TLNN	U,LDLIMI	;IN IMAGE INPUT MODE?
	JRST	RECIN2		;NO.
IFN FTCIMP,<			;[arpa]
RECNXI::			;[arpa] here to send stuff from NetQuo
>				;[arpa]
	MOVEI	T1,IMGTIM	;YES. RESET TIMEOUT FIELD TO MAX
	DPB	T1,LDPTIM	; ..
	TRO	T3,400		;MARK IN NINTH BIT.
	JRST	RECINA		;AND GO STORE IN BUFFER. NO BREAK.
RECIN2:	SKIPG	LDBTIC(U)	;FIRST INPUT CHARACTER ON LINE
	JRST	[PUSHJ	P,HPOS	;YES, GET CURRENT HORIZONTAL POSITION
		DPB	T2,PRPOS;REMEMBER IT FOR ERASING TABS
		JRST	.+1]
IFN FTCIMP,<			;[arpa]
	SKIPN	F,LDBIMP(U)	;[arpa] CROSSPATCHED TO IMP?
	  JRST	RECQRT		;[arpa] NO.
	TRNE	T3,400		;[arpa] YES - SPECIAL CHAR HANDLING?
	  JRST	RECINA		;[arpa] YES - STORE AS IS
	ANDI	T3,177		;[arpa] NO, STRIP PARITY
	pushj	p,RecQuo##	;[arpa] check for network quotes or whatever.
	  popj	p,		;[arpa] it was something and we sent it.
RECQRT:				;[arpa]
>				;[arpa]
	PUSHJ	P,SPCHEK	;SEE IF IT'S SPECIAL. SET T1 UP.
	  JRST RECIN3		;NON-SPECIAL. SEE IF LOWER CASE
IFN FTCIMP,<			;[arpa]
	TLNN	T1,CHXPIH	;[arpa] SPECIAL EVEN IF CROSSPATCHED?
	  JUMPN	F,RECI2A	;[arpa] JUMP IF CROSSPATCHED (F SET UP BEFORE)
>;[arpa]  END IFN FTCIMP
	TLNE	T1,CHRIA	;DOES THIS CHAR NEED SPECIAL RCV HANDLING?
	JRST	0(T1)		;YES. GO TO IT.
				;NO. FALL INTO ORDINARY CHAR HANDLER
IFN FTCIMP,<			;[arpa]
	JRST	RECINA		;[arpa] JUMP AROUND IMP CODE

RECI2A:	TLZ	T1,CHBRK!CHCNC	;[arpa] SUPPRESS SPECIAL HANDLING BECAUSE CROSSPATCHED
	IORI	T3,400		;[arpa] SET IMAGE BIT
> ;[arpa] END FTCIMP
;HERE WITH T1=CHARACTER BITS (LH=0 IF NONE), T3=CHARACTER

IFE FTWATCH,<RICT:>
RECINA:	TRNE	T3,400		;IF THIS IS AN IMAGE MODE CHAR,
	JRST	RECINB		; DON'T TOUCH THE ECHO/PARITY BIT
	TRO	T3,200		;FIRST, ASSUME THAT REMOTE DIDN'T ECHO CHAR
IFN FTNET,<
	MOVE	T2,LDBDCH(U)	;GET THE CHARACTERISTICS, AND
	TRNN	T2,LDRREM	;  IF THIS LINE IS A LOCAL LINE (NOT REMOTE)
	JRST	RECINB		;  THEN THE REMOTE DIDN'T ECHO THE CHAR.
	MOVEI	T2,STY.DE	;GET THE "REMOTE LOCAL ECHO" BIT
	TDNN	T2,LDBREM(U)	; AND IF THE REMOTE IS ECHOING THE CHARS,
	TRZ	T3,200		; THEN CLEAR THE "NEEDS ECHOING" BIT
>
RECINB:	MOVE	T2,LDBTIC(U)	;COUNT CHARACTERS LINE HAS INPUT
	ADD	T2,LDBECC(U)	;PLUS LEFT TO ECHO
	PUSH	P,T1		;SAVE CHARACTER BITS
	CAILE	T2,TTIWRN	;TIME TO WARN HIM?
	JRST	RWARN		;YES.  GO SEND XOFF.
RWARNX:	SCNOFF
	STCHK	T3,LDBTIP(U)	;STORE CHARACTER
	AOS	LDBECC(U)	;COUNT CHARACTER TO ECHO
	POP	P,T1		;RESTORE T1
IFN FTCIMP,<		;[arpa] XPATCHED TTYS DON'T HAVE BREAK CHARACTERS
	SKIPE	LDBIMP(U)		;[arpa] crosspatched?
	  JRST	[			;[arpa] no.  no more nonsense.
		 SCNON			;[arpa] interrupts back on
		 movsi	T2,L2LCCS!L2LDEL;[arpa] set to clear ↑C and <DEL> bits
		 JRST	RECINI		;[arpa] 
		]			;[arpa]
>					;[arpa]
	TLNE	T1,CHBRK	;BREAK CHARACTER?
	PUSHJ	P,SETBKU	;YES, NOTE PLACE
	SCNON
IFN FTMIC,<			;IF MIC
	SKIPE	LDBMIC(U)	;IS HE RUNNING MIC?
	PUSHJ	P,MICECH	;YES - SEE IF <CR> TYPED
> ;END OF IF MIC
	MOVE	S,FLLBSP	;PREPARE BACKSLASH POINTER
	MOVSI	T2,L2LDEL	;WAS PREVIOUS CHAR A RUBOUT?
	TDNN	T2,LDBBY2(U)	; ..
	JRST	RECIN6		;NO
	MOVEM	S,LDBFLP(U)	;YES. STORE BACKSLASH FILLER PTR
	MOVSI	S,LDLFCP	;FORCING FLAG
	IORM	S,LDBDCH(U)	;FLAG FOR XMTCHR
IFN FTLINK,<			;[link]
	PUSH	P,T1		;[link] PRESERVE AGAINST RAVAGES OF TIME
	PUSH	P,T2		;[link] DITTO
	PUSHJ	P,CHKLKF##	;[link] RAVAGES - CHECK FOR FILL LINKS
	POP	P,T2		;[link] UNPRESERVE
	POP	P,T1		;[link] OTTID
> ;[link] END IFN FTLINK
	AOS	LDBHPS(U)	; AND COUNT POSITION OF BACKSLASHES
RECIN6:	TLNN	T1,CHCNC	;IS THIS CHARACTER A CONTROL C?
	TLO	T2,L2LCCS	;NO. PREPARE TO CLEAR L2LCCS BIT
IFN FTCIMP,<RECINI:>		;[arpa] here if crosspatched.
	ANDCAM	T2,LDBBY2(U)	;CLEAR DELETE AND CONTROL C FLAGS
IFN FTLINK,<			;[link]
	TLNN	T1,CHUAE	;[link] ECHO AS ↑X?
	 TLNE	U,LDLNEC	;[link] OR NOT ECHOING AT ALL?
	  JRST	RECLN1		;[link] YES - DON'T ECHO TO LINKS EITHER
	MOVSI	T2,LNKECH	;[link] MARK AS SENDING ECHO TO LINKS
	IORM	T2,LDBLNK(U)	;[link] ....
	PUSH	P,T1		;[link] KEEP IT AROUND
	PUSHJ	P,CHKLNK##	;[link] SEND ECHO TO ANY OPEN LINKS
	POP	P,T1		;[link]
RECLN1:				;[link]
> ;[link] END FTLINK
	PJRST	TOPOKE		;QUE TO GET ECHO STARTED
RECIN3:	TLNN	U,LDLLCT	;DOES HE WANT UPPER?
	JRST	RECIN4		;NOPE, DON'T BOTHER WITH ANYTHING ELSE
ifn FtCImp,<			;[arpa]
	LDB	T2,LDPSFT##	;[arpa] ANY SHIFT CHAR DEFINED?
	JUMPN	T2,RECIN4	;[arpa] YES - BYPASS
	SKIPE	LDBIMP(U)	;[arpa] CROSSPATCHED?
	  jrst	[		;[arpa] yes.  make sure upper case
		 trne	t3,100	;[arpa] character range?
		   trz	T3,40	;[arpa] yes.  make sure upper case.
		 jrst	RecIn4	;[arpa] and skip other checks
		]		;[arpa]
> ;[arpa] END FTCIMP
	LDB	T2,[POINT 7,T3,35]	;GET SEVEN BITS OF CHARACTER
	CAIL	T2,140		;IS IT LOWERCASE (AS DEF .GT. 140)?
	TRC	T3,240		;YES. MAKE UPPER, CORRECT PARITY
RECIN4:
IFN FTCIMP,<			;[arpa]
	SKIPE	LDBIMP(U)	;[arpa] DON'T DO AUTO CRLF IF XPATCHED
	  JRST	RECINA		;[arpa]
>				;[arpa]
	LDB	T4,LDPACR	;GET AUTO CRLF BYTE
	JUMPE	T4,RECINA	;IGNORE IF ZERO
	TLNN	U,LDLCOM
	TRNE	T3,137		;SEE IF SPACE
	JRST	RECINA		;NO--FORGET IT
	PUSHJ	P,HPOS		;GET POSITION ON LINE
	SUBI	T2,(T4)		;SEE IF ROOM
	JUMPL	T2,RECINA	;JUMP IF YES
	MOVEI	T3,215		;ELSE CONVERT TO
	JRST	RECIN2		;CR


;ROUTINE TO REMEMBER THE BREAK CHARACTER POSITION IN LDBBKU

SETBKU:	MOVE	T2,LDBTIP(U)	;LOCATION OF INPUT PUTTER
	MOVEM	T2,LDBBKU(U)	;SAVE IT
	POPJ	P,
IFN FTHDPX,<

RECHDX:	JUMPGE	T1,RECIN1	;IF NOT OUTPUTTING, TREAT AS KEYBOARD FLAG
	MOVE	T1,LDBBY2(U)	;OUTPUTTING. CONSIDER ECHO.
	TLNE	T1,L2LHD3	;DURING IGNORE TIME?
	POPJ	P,0		;YES. IGNORE.
	MOVSI	T1,L2LHD2	;FLAG FOR RCV INT
	LDB	T2,LDPECK	;NO. GET CHAR LAST SENT OUT
	CAIE	T2,0(T3)	;IS IT CORRECT?
	TLO	T1,L2LHD5	;NO. PUT ERROR FLAG IN TOO
	IORB	T1,LDBBY2(U)	;SET RCV DONE AND ERROR IF ERROR OCCURRED
IFE FT630H,<
	TLNN	T1,L2LHD1	;HAS XMT FLAG HAPPENED TOO?
	POPJ	P,0		;NO. WAIT FOR IT.
>
RHDERQ:	TLNN	T1,L2LHD5	;ERROR ON RCV INT?
	JRST	XMTHCH		;NO, PROCESS AS TRANSMIT DONE
				;YES. FALL INTO ERROR ROUTINE
RHDERR:	MOVSI	T1,L2LHD4	;IS THIS AN ERROR OR THE RESPONSE TO IT?
	TDNN	T1,LDBBY2(U)	; ..
	JRST	RHDER1		;ERROR.
	ANDCAM	T1,LDBBY2(U)	;RESPONSE. CLEAR RESP FLAG
	MOVE	T2,T3		;CONSIDER WITHOUT PARITY
	ANDI	T2,177		; ..
	CAIN	T2,"O"-100	;CONTROL O?
	JRST	RHDER2		;YES.
	CAIE	T2,"C"-100	;CONTROL C?
	JRST	XMTHCH		;NO, TREAT AS TRANSMIT DONE
	MOVSI	T1,L2LCCS	;YES. MAKE IT LOOK LIKE TWO OF THEM
	IORM	T1,LDBBY2(U)	; ..
RHDER2:	MOVSI	T1,LDLIDL
	IORM	T1,LDBDCH(U)
	MOVSI	T1,LPLIRM
	ANDCAM	T1,LDBPAG(U)
	JRST	RECIN1		;AND GO PROCESS AS RECEIVE INTERRUPT

RHDER1:	MOVSI	T1,L2LHD3+L2LHD4	;ERROR. FLAG FOR IGNORE RCV INTS
	IORM	T1,LDBBY2(U)	; ..
	AOS	T1,ECHCNT	;UPDATE COUNTER
	CAILE	T1,10		;TOO MANY CLOCK REQUESTS?
	JRST	ECHOUT		;YES
	MOVE	T1,TICSEC##	;DELAY FOR HALF SECOND
	LSH	T1,-1
	HRLI	T1,ECHO		;COME TO ECHO AFTER DELAY
	SYSPIF			;PUT REQUEST IN CLOCK QUEUE
	IDPB	T1,CLOCK##	; ..
	IDPB	U,CLOCK##
	SETOM	CLKNEW##
	JRST	ONPOPJ##	;ENABLE INTERRUPTS AND RETURN

ECHOUT:	SOS	ECHCNT		;SO COUNT STAYS RIGHT
	JRST	ONPOPJ##	;ONE LESS QUEUE ENTRY
ECHO:	MOVSI	J,MTTYLN##	;HERE AT CLK LEVEL. CLEAR TERMINAL IGNORE FLAGS
	MOVSI	T1,L2LHD3	;IN ALL TTY LDB'S
	SOS	ECHCNT		;ONE LESS QUEUE ENTRY
ECHOL:	HRRZ	U,LINTAB##(J)	;GET AN LDB ADDRESS
	ANDCAM	T1,LDBBY2(U)	;CLEAR IGNORE BIT
	AOBJN	J,ECHOL		;DO FOR ALL LINES
	POPJ	P,0		;RETURN TO CLOCK LEVEL
>
;HERE ON RECEIVE INTERRUPT OF A CONTROL-C CHARACTER

IFN FTMIC,<			;IF MIC
RICA:	SKIPN	LDBMIC(U)	;IS MIC RUNNING FOR US?
	JRST	RECINA		;NO NORMAL CONTROL CHAR
				;YES - FALL INTO RICC

RICC:	PUSH	P,T1		;SAVE CHARACTER BITS
	SKIPE	T1,LDBMIC(U)	;IS MIC RUNNING FOR US?
	PUSHJ	P,MICRIC	;YES - EXTRA GOODIES
> ;END OF IF MIC
IFE FTMIC,<			;IF NOT MIC
RICC:	PUSH	P,T1		;SAVE CHARACTER BITS
> ;END OF IF NOT MIC
	PUSH	P,T3		;RIDLN CLOBBERS T3
	PUSHJ	P,RIDLN		;DO THE CONTROL-U FUNCTION
	POP	P,T3		;RECOVER ↑C FOR ECHO
	HRRZ	F,LDBDDB(U)
	JUMPE	F,RICC2
	LDB	J,PJOBN##
	LDB	T1,LDPDEB	;DEFERRED ECHO BITS
	DPB	T1,JBYDEB##	;SAVE IN JOB TABLE
RICC2:	MOVSI	T1,L2LCCS	;SEE IF SECOND CONTROL C
	TDNN	T1,LDBBY2(U)	; ..
	JRST	RICC1		;NO
IFN FTTPAG,<
	MOVSI	T1,LDLSTP+LDLSSO;YES - CLEAR STOP BIT
	ANDCAM	T1,LDBDCH(U)
>
	PUSHJ	P,CNCCHK	;YES. AM I ALLOWED TO BELIEVE THE CONTROL-C?
	  JRST RICC1		;SLAVE, OR NOT SECOND. JUST STORE
	PUSHJ	P,TTHALT	;JACCT AND TWO ↑C↑C
	HRRZ	F,LDBDDB(U)	;GET ATTACHED JOB
	JUMPE	F,RICC3		;MAKE SURE THERE IS ONE
	MOVE	T1,DEVMOD(F)	;IS OWNING JOB ATTACHED TO TERMINAL,
	TLNE	T1,TTYATC	;OR JUST USING TERMINAL AS IO DEVICE?
	JRST	RICC3		;ATTACHED. OK TO DO CONTROL C
	MOVEI	S,IODERR	;NOT ATTACHED
	IORB	S,DEVIOS(F)	;GIVE JOB AN ERROR BIT
	PUSHJ	P,TTWAKE	;AND WAKE IT UP
	SETZM	DEVNAM(F)	;MAKE IT INVISIBLE TO DEVSRC
	PUSH	P,U		;SAVE U IN CASE DDB IS KILLED
	PUSHJ	P,PTYDET	;GET LINE FREE OF DDB
	POP	P,U		;RESTORE U
RICC3:	POP	P,T1		;RESTORE STACK LEVEL
	PUSHJ	P,TSETBI	;FORCE ACTION. CLEAR BUFFERS
	PUSHJ	P,TSETBO	;BOTH INPUT AND OUTPUT. COMCON HAS
				; BEEN FLAGGED BY CNCCHK
	MOVE	T2,FILXCP	;POINTER TO CONTROL C ECHO
	JRST	RIFRET		;STORE IT AND RETURN

RICC1:	MOVSI	T1,L2LCCS	;SET "↑C LAST IN" BIT
	IORM	T1,LDBBY2(U)	;NOT SECOND. STORE BIT.
	JRST	RICQ2		;AND TREAT AS RCV CHARACTER
;HERE ON RECEIPT OF A ↑D CHARACTER

	$LOW
RICD:	MOVEI	T2,LDRDSR	;DATASET OR REMOTE
	TDNE	T2,LDBDCH(U)	; ..
	JRST	RECINA		;YES--SAY ↑D
	HLRZ	T2,CD		;GET INSTRUCTION
	CAIE	T2,(JSR)	;BREAK POINT
	JRST	RECINA		;NO--IGNORE
	MOVEM	17,CDSAV+17	;SAVE 17
	MOVEI	17,CDSAV	;PLACE TO SAVE ACS
	BLT	17,CDSAV+16	;SAVE THEM
				;PLACE BREAKPOINT HERE . . .
CD::	MOVSI	17,CDSAV	;RESTORE ALL ACS
	BLT	17,17		;AND
	POPJ	P,		;RETURN FROM INTERRUPT
CDSAV:	BLOCK	20		;PLACE TO SAVE ACS AT CD BREAKPOINT
	$HIGH
;HERE ON CONTROL H (BACKSPACE) TO DETERMINE HOW TO TREAT
;IN THE VARIOUS CASES LIKE APL ETC.

RIBSP:	PUSHJ	P,SAVE3##	;SAVE P1-P3
	PUSHJ	P,STOPCM
	HLLZ	P1,T1		;SAVE CHARACTER BITS
	LDB	T2,LDPAPL	;GET APL BIT
	JUMPN	T2,RECINA	;JUST STORE IN BUFFER (THIS APL)
IFN FTCAFE&FT2741,<
	MOVEI	T1,LDR2741	;IF 2741...
	TDNE	T1,LDBDCH(U)	;NON APL
	MOVEI	T3,377		;ACT LIKE RUBOUT
>;END OF FTCAFE&FT2741
	JRST	RIDELB
;HERE ON RECEIPT OF A CARRIAGE RETURN (CONTROL M)

RICM:	MOVEI	T2,L2RXON	;IS XON TRUE?
	TDNE	T2,LDBBY2(U)	;...
	JRST	RECINA		;YES. NOTHING SPECIAL. STORE.
	PUSHJ	P,RECINA	;NO. FIRST STORE THE C-R
	MOVEI	T3,12		;THEN GET A L-F (EVEN PARITY)
	JRST	RECIN1		;AND GO PRETEND IT WAS TYPED IN.

;HERE ON RECEIVE INTERRUPT OF A CONTROL O

RICO:	MOVEI	T1,LDROSU	;COMPLEMENT STATE OF OUTPUT SUPPRESS BIT
	XORM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
	DPB	T1,LDPSVC	;CLEAR ANY SAVED CHARACTER
IFN LDROSU&777,<PRINTX ?LDROSU AND LDPSVC CONFLICT>
	PUSHJ	P,TSETBO	;CLEAR OUTPUT BUFFER
	MOVE	T2,FILXOP	;POINTER TO ↑O ECHO
	JRST	RIFRET		;STORE AND RETURN

;HERE TO DISCARD INPUT CHARACTER SUCH AS NULL OR "USED" ↑O

	RINUL==CPOPJ##		;RETURN FROM RECINT.
;HERE ON RECEIVE INTERRUPT OF A CONTROL Q (XON)

RICQ:	PUSH	P,T1		;SAVE CHARACTER BITS
	MOVSI	T1,L2LTAP	;HAS TERMINAL TAPE COMMAND BEEN TYPED?
	TDNN	T1,LDBBY2(U)	; ..
	JRST	RICQ2A		;NO. DON'T DO ANYTHING SPECIAL
	MOVEI	T1,L2RXON	;TURN ON BIT IN LINE CHAR WORD
	IORM	T1,LDBBY2(U)	; ENTER HERE FOR OTHER BITS TOO
	MOVEI	T1,ISRCHP
	PUSHJ	P,@LDBISR(U)	;TELL REMOTE STATION ABOUT THE ↑Q.
	POP	P,T1
	JRST	CHKXN1
RICQ2A:
IFN FTTPAG,<
	MOVSI	T1,LDLSTP+LDLSSO;CLEAR STOP BIT FOR TERMINAL OUTPUT
	ANDCAM	T1,LDBDCH(U)	;..
	MOVSI	T1,LPLPAG	;HAS "SET TERMINAL PAGE" BEEN ENABLED
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] ALWAYS SEND IF CROSSPATCHED
>				;[arpa] END IFN FTCIMP
	TDNN	T1,LDBPAG(U)	;..
	JRST	RICQ2		;NO, DON'T DO ANYTHING SPECIAL WITH ↑Q
IFN FTTVP,<PUSHJ P,CLRPCT>	;CLEAR PAGE COUNTER
	MOVEI	T1,ISRCHP	;TELL REMOTE STATION ABOUT ↑Q
	PUSHJ	P,@LDBISR(U)
	POP	P,T1		;RESTORE T1
	PJRST	TOPOKE		;AND GO START OUTPUT AGAIN
> ;IFN FTTPAG

RICQ2:	POP	P,T1		;RESTORE CHARACTER BITS
	JRST	RECINA		;AND ACCEPT THE CHARACTER
IFN FTMIC,<			;IF MIC

;HERE ON RECEIVE INTERRUPT OF CONTROL P (PROCEED)

RICP:	SKIPN	T2,LDBMIC(U)	;IS MIC RUNNING FOR US?
	JRST	RECINA		;NO - JUST RETURN
	TLO	T2,LDLCHK!LDLMCP;YES - SET UP ↑P FLAG
RICB2:	MOVEM	T2,LDBMIC(U)	;PUT WORD BACK
RICB3:	PJRST	MICWAK		;WAKE UP MIC

;HERE ON RECEIVE INTERRUPT OF CONTROL B (BREAK)

RICB:	SKIPN	T2,LDBMIC(U)	;IS MIC RUNNING FOR US?
	JRST	RECINA		;NO TREAT AS ORDINARY CHAR
	TLO	T2,LDLCHK!LDLMCB;YES - SET UP ↑B FLAG
	JRST	RICB2		;AND TREAT AS ↑P
> ;END OF IF MIC
;HERE ON A CONTROL T
IFN FTWATCH,<
RICT:	PUSHJ	P,DOCTLT	;PROCESS THE CONTROL-T
	  JRST	RECINA		;WE WANT TO STORE IT
	  JRST	[PUSHJ P,CLRPCT
		 JRST TTFORC]	;WE WANT TO DO USESTAT
	JRST	RIBUSY		;LINE ALREADY HAS A COMMAND

DOCTLT:
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] ALWAYS SEND IF CROSSPATCHED
>				;[arpa] END IFN FTCIMP
	LDB	T2,LDPRTC	;GET BIT FOR TERMINAL RTCOMPAT
	JUMPN	T2,CPOPJ##	;IF IT IS =1 GIVE NON-SKIP RETURN
	HLL	U,LDBDCH(U)	;GET DEVICE FLAGS
	TLNE	U,LDLSLV	;SLAVE?
	JRST	CPOPJ##		;YES--DO NOT FORCE CONTROL-T
	HRRZ	F,LDBDDB(U)	;GET LINKED DDB ADDRESS
	JUMPE	F,RICT1		;FORCE COMMAND IF ZERO
	MOVE	T2,DEVMOD(F)	;GET DEVICE BITS
	TLNN	T2,TTYATC	;CONTROLLING TERMINAL?
	JRST	CPOPJ##		;NO--JUST STORE THE CONTROL-T
RICT1:	MOVEI	T1,TTFCXW	;FORCE USESTAT
	SKIPL	(U)		;COMMAND ALREADY PENDING?
	JRST	CPOPJ1##	;NO--GIVE SINGLE SKIP
	JRST	CPOPJ2##	;YES--GIVE DOUBLE SKIP
> ;END FTWATCH
;HERE ON A CONTROL R

RICR:
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] ALWAYS SEND IF CROSSPATCHED
>				;[arpa] END IFN FTCIMP
	LDB	T2,LDPRTC	;RTCOMPATABILITY IN EFFECT?
	JUMPN	T2,RECINA	;JUMP IF SO, STORE CHARACTER IN THE INPUT BUFFER
	PUSHJ	P,FULLCQ	;COMMAND OR FULL CHARACTER SET?
	  JRST	RECINA		;YES, STORE CHARACTER
	SETZ	T3,		;ASSUME NOT A VIDEO TERMINAL
	PUSHJ	P,TTVID		;IS IT?
	  JRST	RICR2		;NO, NOTHING FANCY TO DO
	HLRZ	T3,TCRTAB+1(T1)	;ADDRESS OF EOL TABLE
	JUMPE	T3,RICR2	;VIDEO TERMINAL BUT CAN'T DO EOL
	MOVSI	T3,LDLUAR	;DOING CONTROL R
	PUSHJ	P,HPOS		;CURRENT HORIZONTAL POSITION
	LDB	T4,PRPOS	;LENGTH OF THE PROMPT
	CAMN	T2,T4		;CURSOR AT THE END OF THE PROMPT?
	JRST	RICR1		;YES, NOTHING TO SKIP OVER
	LDB	T2,LDPFCT	;FILLER REPEAT COUNT
	JUMPN	T2,RICR1	;IF NON-ZERO, THE PROMPT HAS BEEN SPACED OVER
	IORM	T3,LDBTTW(U)	;PROMPT HASN'T BEEN SPACED OVER SO INDICATE ↑R PROCESSING
	JRST	RICU2		;AND USE ↑U CODE TO SKIP THE PROMPT
RICR1:	ANDCAM	T3,LDBTTW(U)	;DONE WITH ↑R PROMPT PROCESSING
	DPB	T3,LDPSVC	;NO LEFT OVER CHARACTER
	DPB	T3,LDPFCT	;AND NO FILLER COUNT
	MOVEI	T2,0		;FILL POINTER
	PUSHJ	P,SETFLP	;ZAP
RICR2:	MOVEI	T1,TTFCXT	;RETYPE THE LINE
	SKIPGE	(U)		;IS THERE ALREADY AN OUTSTANDING COMMAND?
	JRST	RIBUSY		;YES, SAY BUSY
	PUSHJ	P,TTFORC	;FORCE THE RETYPE COMMAND
	JUMPN	T3,CPOPJ##	;ALL DONE IF NOT A HARDCOPY TERMINAL
	MOVE	T2,FLLBSC	;HARDCOPY,
	PJRST	RIFRET		; RETYPE ON A NEW LINE
;HERE ON RECEIVE INTERRUPT OF CONTROL S (XOFF)

RICS:	PUSH	P,T1		;SAVE CHARACTER BITS
	MOVEI	T1,L2RXON	;CLEAR THIS BIT
	ANDCAM	T1,LDBBY2(U)	;IN LINE CHARACTERISTICS WORD
	MOVSI	T1,LDLSTP	;GET THE "STOPPED BY ↑S BIT"

IFN FTTPAG,<
	PUSHJ	P,STPOIP
	  JRST	RICQ2
	JRST	TPOPJ##
>
IFE FTTPAG,<JRST RICQ2>

IFN FTTPAG,<
STPOIP:	MOVSI	T2,LPLPAG	;HAS "SET TERMINAL PAGE" BEEN ENABLED?
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] ALWAYS SEND IF CROSSPATCHED
>				;[arpa] END IFN FTCIMP
	TDNN	T2,LDBPAG(U)	;...
	POPJ	P,		;NO, DON'T DO ANYTHING SPECIAL
	IORM	T1,LDBDCH(U)	;NO MORE OUTPUT UNTIL XON IS TYPED
IFN FTTVP,<
	PUSHJ	P,CLRPCT
>
	PUSHJ	P,SETCHP	;TELL FE'S TO STOP NOW
	JRST	CPOPJ1##
> ;IFN FTTPAG

BEATIT:	SKIPA	T2,[POINT 9,GAWTXT-1,26]
RIBUSY:	MOVE	T2,[POINT 9,BSYTXT]
	JRST	RIFRET

BSYTXT:	BYTE	(9)134,102,165,163,171,FLLFLG
GAWTXT:	BYTE	(9)123,164,341,356,344,240,341,154,157,356,145,FLLFLG

IFN FTTVP,<
;ROUTINES TO IMPLEMENT 'TERMINAL PAGE N'

CLRPCT::SETZ	T2,
	DPB	T2,LDPPCT	;CLEAR COUNTER
	POPJ	P,

INCPCT:	LDB	T2,LDPPCT
	ADDI	T2,1
	DPB	T2,LDPPCT
;;	PJRST	CHKPCT

CHKPCT:
IFN FTCIMP,<			;[arpa] DISABLE AUTO STOP FOR IMPS
	SKIPE	LDBIMP(U)	;[arpa] cross patched out?
	  pjrst	ClrPct		;[arpa] yes.  clear count, don't stop
>				;[arpa]
IFN FTNET,<
	MOVE	T1,LDBREM(U)	;GET THE REMOTE BITS,
	TLNN	T1,LRLVTM	;  AND IF THIS IS A VTM LINE
>
	PUSHJ	P,PTBTCH##	;CHECK FOR BATCH PTY
	  POPJ	P,		;DISABLE AUTO STOP FOR BATCH OR VTM LINES
	LDB	T1,LDPPSZ	;PAGE SIZE
	JUMPE	T1,CPOPJ##	;IF NO AUTO PAGE SELECTED
	CAIGE	T2,-1(T1)	;COMPARE COUNT WITH SIZE, ALLOW FOR LAST LF
	POPJ	P,
	MOVSI	T1,LDLSSO	;GET "SCNSER STOPPED OUTPUT" BIT
	PUSHJ	P,STPOIP	;IF AT LIMIT, STOP OUTPUT, CLEAR COUNT
	  POPJ	P,		;STPOIP NON-SKIPS IF TERMINAL NO PAGE
	MOVE	T2,[POINT 9,[BYTE (9)207]] ;A LONE BELL
	PJRST	SETFLP		;REMIND THE USER OF TTY PAGE N
>
;PACKED IMAGE MODE (PIM) RECEIVE CHARACTER PROCESSING

REPIM:
IFN FTTPAG,<
	MOVSI	T2,LPLPAG
	TDNN	T2,LDBPAG(U)	;HAS SET TERMINAL PAGE BEEN DONE?
	JRST	REPIM3		;NO, DON'T LOOK FOR XON/XOFF
	CAIE	T3,221		;THIS CHARACTER AN XON?
	CAIN	T3,21		;IN EITHER PARITY?
	JRST	RICQ		;YES, TREAT AS NON PIM XON
	CAIE	T3,223		;OR IS IT AN XOFF
	CAIN	T3,23		;
	JRST	RICS		;TREAT AS NON PIM XOFF IF SO
>;END OF FTTPAG
REPIM3:	MOVE	T2,LDBTIC(U)	;# OF CHARS INPUT
	CAMG	T2,RPIMWN	;TIME TO WARN HIM?
	JRST	REPIM2		;NO, NOT YET
	SUBI	T2,↑D20		;IS HE OVER 20 CHARS?
	CAMLE	T2,RPIMWN	;OVER CURRENT LIMIT?
	JRST	[MOVE	T1,LDBPAG(U)
		 TLNN	T1,LPLXOF	;SENT XOF YET?
		 JRST	RPIM25		;NO, DO IT NOW
		 JRST	RCHLT1]		;YES, EAT CHAR
RPIM25:	PUSHJ	P,SNDXOF	;SEND XOFF
	PUSHJ	P,RCVWAK
REPIM2:	SKIPG	TTFREN##	;ROOM IN CHUNK SPACE?
	JRST	RCHLT2		;NO, SHUT IT DOWN
	TRO	T3,400		;MARK NINTH BIT
	SCNOFF			;NO INTERRUPTS
	STCHK	T3,LDBTIP(U)	;PLACE CHARACTER IN BUFFER
	AOS	LDBTIC(U)	;INCREMENT COUNT
	SETZM	LDBECC(U)
	MOVE	T2,LDBTIP(U)
	MOVEM	T2,LDBECT(U)	;MAKE CHAR LOOK ECHOED
	SCNON			;ALLOW INTERRUPTS
	SKIPN	T2,LDBPBK(U)	;GET AND TEST BREAK CHARACTER WORD
	JRST	RCVWAK		;NOTHING SPECIFIED, BREAK ON ALL
	ANDI	T3,377		;CLEAR NINTH BIT FOR TEST
REPIM1:	LSHC	T1,9		;GET TEST CHARACTER
	XOR	T1,T3		;XOR WITH RECEIVED CHAR
	TRNN	T1,377		;MATCH?
	JRST	RCVWAK		;YES, BREAK CHAR, WAKE AND DISMISS
	JUMPE	T2,CPOPJ##	;DONE, DISMISS INTERRUPT
	JRST	REPIM1		;NO, TRY NEXT
SNDXOF::MOVSI	T1,LPLXOF	;GET THE "XOFF HAS BEEN SENT" BIT
	TDNE	T1,LDBPAG(U)	;HAVE WE SENT ONE?
	POPJ	P,		;IF SO, DON'T SEND TWO
	IORM	T1,LDBPAG(U)	;SET THE BIT SO WE DON'T SEND ANOTHER
	PUSH	P,T3		;ISR WILL CLOBBER THIS
	MOVEI	T3,1		;CODE TO SAY BUFFER LOW
	MOVEI	T1,ISRREM	;
	PUSHJ	P,@LDBISR(U)	;NOW CALL ISR
	  SKIPA	T2,FLPPXF	;ISR DID'T SEND IT. WE MUST
	JRST	T3POPJ		;XOFF SENT, POP T3 AND RETURN
	PUSHJ	P,SETXNP	;SET FILLER
	PUSHJ	P,TOPOKE	;MAKE SURE IT GETS OUT
	POP	P,T3		;RESTORE T3
	POPJ	P,		;RETURN

;HERE ON A CONTROL U AT INTERRUPT LEVEL ONLY

RICU:	PUSHJ	P,FULLCQ	;BREAK ON ALL CHARACTERS?
	  JRST RECINA		;YES. STORE THE ↑U IN BUFFER
	LDB	T1,LDPFCT	;FILLER REPEAT COUNT
	JUMPN	T1,RICU1	;JUMP IF NOT THE FIRST TIME
	PUSHJ	P,RIDLN		;BACKUP THE INPUT BUFFER TO THE LAST BREAK CHARACTER
	SKIPL	LDBDCH(U)	;LINE IDLE?
	JRST	RINUL		;NO, GO AWAY
	MOVE	T2,FILXUP	;ASSUME HARDCOPY \↑U<CRLF>
RICU1:	PUSHJ	P,TTVID		;VIDEO TERMINAL?
	  JRST	RIFRET		;NO, ECHO TRADITIONAL STUFF
RICU2:	PUSHJ	P,HPOS		;HORIZONTIAL POSITION
	LDB	T3,PRPOS	;LENGTH OF THE PROMPT
	CAMN	T2,T3		;AT THE END OF THE PROMPT?
	JUMPN	T3,RINUL	;YES, NOTHING TO DO
	HLRZ	T2,TCRTAB+1(T1)	;ADDRESS OF THE ERASE TABLE
	JUMPE	T2,[MOVE T2,FILXUP ;VIDEO TERMINAL BUT CAN NOT DO EOL
		    JRST RIFRET]
	JUMPE	T3,[MOVEI T1,1	;IF NO PROMPT, I.E. AT LEFT MARGIN,
		    AOJA T2,RICU4] ;CARRIAGE RETURN, ERASE END OF LINE
	LDB	T1,LDPFCT	;FILLER REPEAT COUNT
	JUMPN	T1,RICU3	;JUMP IF SPACING OVER THE PROMPT
	DPB	T3,LDPFCT	;REMEMBER NUMBER OF CHARACTERS TO SPACE OVER
	MOVE	T2,(T2)		;CARRIAGE RETURN
	MOVEI	T1,25		;DOING CONTROL U
	DPB	T1,LDPSVC	;REMEMBER THAT TO GET BACK HERE
	JRST	RIFRT1		;SET HPOS TO BEGINNING OF LINE AND TYPE CARRIAGE RETURN
RICU3:	CAIE	T1,1		;AT LAST CHARACTER OF THE PROMPT?
	SKIPA	T2,1(T2)	;NO, CURSOR RIGHT
RICU4:	MOVE	T2,2(T2)	;YES, CURSOR RIGHT, ERASE END OF LINE
	MOVSI	T4,LDLUAR	;CONTROL R BIT
	TDNE	T4,LDBTTW(U)	;PROCESSING CONTROL R?
	CAIE	T1,1		;YES, LAST CHARACTER OF THE PROMPT BEEN SPACED OVER?
	SOSA	T1		;NO, DECREMENT LENGTH OF THE PROMPT
	SKIPA	T4,[22]		;CONTROL R PROCESSING
	MOVEI	T4,25		;CONTROL U OR MORE CONTROL R
	DPB	T1,LDPFCT	;UPDATED FILLER REPEAT COUNTER
	DPB	T4,LDPSVC	;POST PROCESSING DISPATCH
	SKIPN	T1		;IF LAST CHARACTER,
	DPB	T1,LDPSVC	;NO POST PROCESSING
	JUMPE	T3,RIFRT1	;DONE IF NO PROMPT
	MOVEI	T3,40		;SPACE
	PUSHJ	P,ADJHP		;ADJUST HORIZONTAL POSITION 1 CHARACTER TO THE RIGHT
	JRST	RIDEL3		;SPACE OVER PROMPT CHARACTER
RIDLN:	PUSHJ	P,STOPCM	;STOP COMCON
	SCNOFF			;NO INTERRUPTS
RIDLN1:	SKIPN	T1,LDBBKU(U)	;ANY BREAK POSITION SAVED?
	PJRST	TSETI2		;NONE THERE. MEANS ONLY THIS LINE IN BFR
	CAME	T1,LDBTIP(U)	;ANYTHING TO DELETE ?
	PUSHJ	P,DELCHR	;DELETE 1 CHAR
	  JRST	SONPPJ		;NOTHING LEFT TO DELETE
	JRST	RIDLN1		;LOOP OVER LINE

DELCHR:	SOSGE	T3,LDBECC(U)	;ANY LEFT TO ECHO?
	JRST	[SETZB	T3,LDBECC(U)	;CLEAR ECHO COUNT
		SOSL	LDBTIC(U)	;CHECK FOR UNECHOED INPUT
		JRST	DELCH3		;GO ERASE THOSE TOO
		SETZM	LDBTIC(U)	;CLEAR INPUT COUNT
		MOVE	T1,LDBTIP(U)
		MOVEM	T1,LDBECT(U)	;ENSURE EMPTY ECHO STREAM
		POPJ	P,]		;RETURN
DELCH3:	MOVE	T1,LDBTIP(U)	;GET INPUT PUTTER
	ADD	T1,[9B5]	;BACK 1 BYTE
	TLNE	T1,400000	;CHECK FOR BIT OVERFLOW
	SUB	T1,[<↑D36>B5+1]	;BACK TO PREVIOUS WORD
	MOVEI	T2,CK.BDY##(T1)	;SEE IF HIT HEADER WORD
	TRNN	T2,CK.BDY##	;WELL...
	JRST	[HLRZ	T1,CK.BTH##(T2)	;BACKUP
		JUMPE	T1,CL0STP	;IF A ZERO POINTER, MUST DIE
		ADD 	T1,[POINT 9,CK.BDY##,35] ;MAKE INTO BYTE POINTER
		JRST	.+1]
	MOVEM	T1,LDBTIP(U)	;STORE ADJUSTED POINTER
	JUMPN	T3,CPOPJ1##	;IF NO ECHO STREAM INTACT
	MOVEM	T1,LDBECT(U)	;NO, MAKE SURE IT STARTS CORRECTLY
	JRST	CPOPJ1##

ZAPIN:	SCNOFF			;OOPS, COUNT WENT NEGATIVE
	SETZM	LDBBKC(U)
	SETZM	LDBTIC(U)
	SETZM	LDBECC(U)	;CLEAN UP INPUT
	MOVE	T2,LDBTIT(U)	; COUNTERS AND
	MOVEM	T2,LDBTIP(U)	; POINTERS,
	MOVEM	T2,LDBECT(U)	; INCLUDING ECHO
	PJRST	SONPPJ
RWARN:	CAIGE	T2,TTIMAX	;IF HE IS WAY OVER, OR
	SKIPG	TTFREN##	;WE ARE OUT OF CHUNKS
	JRST	RECHLT		;THROW AWAY THE INPUT CHARACTER
	PUSHJ	P,PTBTCH##	;CHECK IF OLD PTY OR BATCH
	  JRST	RWARNX		; CAN'T SEND XOFF
	PUSHJ	P,SNDXOF	;SEND XOFF
	JRST	RWARNX		;CONTINUE INPUT ROUTINE

RECHLT:	POP	P,T1		;RESTORE T1
RCHLT1::MOVE	T2,FLPBEL	;THIS IS TOO MUCH. TELL HIM
	PUSHJ	P,SETXNP	;SET FILLER FLAG
	MOVEI	T3,2		;CODE FOR CHAR NOT STORED
	MOVEI	T1,ISRREM
	PUSHJ	P,@LDBISR(U)	;TELL THE ISR CHAR NOT STORED
RCHLT2:	PUSHJ	P,TOPOKE	;START TYPING IF NEEDED (USUALLY NOT NEEDED)
	PJRST	ECHBRK		;TRY TO WAKE JOB, THEN
				;DISMISS INTERRUPT, JUNKING CHARACTER

RECVRG:	SCNOFF			;NO INTERRUPTS
	SKIPE	T1,LDBTIT(U)	;IF ANY POINTER
	JRST	RECVR1		;IF POINTER ALREADY EXISTS
	PUSHJ	P,GETCKZ	;GET A FREELIST CHUNK
	ADD	T1,[POINT 9,1,8];MAKE INTO A BYTE POINTER
	MOVEM	T1,LDBTIT(U)	;SET TAKER
RECVR1:	MOVEM	T1,LDBTIP(U)	;SET PUTTER BACK TO TAKER
	MOVEM	T1,LDBECT(U)	;AND THE ECHO POINTER
	SETZM	LDBBKU(U)	;BREAK LOCATION
	JRST	SONPPJ
;HERE ON A RUBOUT OR CONTROL W AT INTERRUPT LEVEL

RIDEL:	PUSHJ	P,SAVE3##	;SAVE P1-P3
	PUSHJ	P,STOPCM
	HLLZ	P1,T1		;SAVE CHARACTER BITS
RIDELB:	PUSHJ	P,FULLCQ	;BREAK ON ALL CHARS, OR FCS?
	  JRST	RECINA		;YES. STORE THE RUBOUT
	LDB	P2,LDBTIP(U)	;GET CHARACTER TO BE ERASED
	ANDI	P2,177		;ONLY 7 BITS
	TLNE	P1,CHDELW	;CONTROL W?
	JRST	RIDELX		;IGNORE PAPER TAPE BITS
	MOVEI	T2,L2RXON	;PAPER TAPE IN EFFECT?
	TDNE	T2,LDBBY2(U)	;YES, DISCARD RUBOUT
	JRST	RINUL		;YES. DISCARD RUBOUT
RIDELX:	HLR	P1,CHTABL(P2)	;GET BITS FOR CHARACTER BEING DELETED
	MOVSI	T2,LDLNAN	;ALPHA-NUMERIC BIT
	LDB	T1,LDPFCT	;FILLER REPEAT COUNT
	JUMPN	T1,RIDELY	;JUMP IF NOT FIRST TIME
	TLNE	P1,CHDELW	;CONTROL W?
	TRNE	P1,CHPUNC	;SKIP IF NOT A PUNCTUATION CHARACTER
	JRST	RIDEL5		;NO, GO DO DELETE
	MOVEI	T1,1		;NOT REALLY A FILLER COUNT
	DPB	T1,LDPFCT	;BUT IT CAUSES US TO GET HERE AGAIN
	MOVSI	T2,LDLUAW!LDLNAN;INDICATE
	CAIE	P2,11		;A TAB?
	CAIN	P2,40		; OR A SPACE
	TLZ	T2,LDLNAN	;NO, ALPHANUMERIC NOT SEEN YET
	JRST	RIDELW		;GO DELETE THIS CHARACTER
RIDELY:	CAIE	P2,11		;A TAB?
	CAIN	P2,40		;OR A SPACE?
	JRST	[TDNN T2,LDBTTW(U) ;YES, ALREADY ERASED AN ALPHA-NUMERIC?
		JRST RIDEL5	;NO, ERASE IT
		JRST RIDELZ]	;YES, EVERY THING THE USER WANTED ERASED HAS BEEN
	TRNE	P1,CHPUNC	;IS THIS CHARACTER PUNCTUATION?
	JRST	RIDELZ		;YES, ALL DONE ERASING
RIDELW:	IORM	T2,LDBTTW(U)	;NO, REMEMBER THAT AN ALPHA-NUMERIC CHARACTER WAS SEEN
	JRST	RIDEL5		;AND GO DELETE THE CHARACTER
RIDELZ:	MOVSI	T1,LDLUAW!LDLNAN;NO LONGER PROCESSING CONTROL W
	ANDCAM	T1,LDBTTW(U)	;CLEAR ALPHA-NUMERIC REMINDER
	DPB	T1,LDPFCT	;AND FILLER REPEAT COUNT
	POPJ	P,		;THE WORD HAS BEEN ERASED SO GO AWAY
RIDEL5:	PUSHJ	P,TTVID
	  TDZA	P3,P3
	HRRZ	P3,TCRTAB+1(T1)
	SKIPE	LDBECC(U)	;IF BAD DATA NOT YET ECHOED
	TLO	U,LDLNEC	;DON'T ECHO ERASURE
	SCNOFF			;NO INTERRUPTS HERE
	MOVE	T2,LDBTIP(U)	;GET ADDRESS OF INPUT STREAM
	CAMN	T2,LDBBKU(U)
	JRST	RIDEL1
	PUSHJ	P,DELCHR	;DELETE THE LAST INPUT CHARACTER
	  JRST	RIDEL1		;IF INPUT STRING DELETED
	SCNON			;ALLOW INTERRUPTS NOW
RIDEL6:	TLNN	P1,CHDEL	;RUBOUT?
	SETZ	P2,0		;NO--SPECIAL ECHO
IFN FTCIMP,<			;[arpa]
	MOVEI	T2,1		;[arpa] set A PHONY BYTE POINTER TO A NULL
	TLNN	U,LDLNEC	;[arpa] echoing?
	 skipe	LDBIMP(U)	;[arpa] yes.  crosspatched?
	  JRST	RIDEL3		;[arpa] crosspatched or not echoing: don't
				;[arpa]  type character after slash.
	DPB	P2,LDPSVC	;[arpa] SAVE FOR AFTER BACKSLASH
>				;[arpa]
ife FtCImp,<			;[arpa]
	TLNN	U,LDLNEC	;UNLESS NO ECHO
	DPB	P2,LDPSVC	;SAVE FOR AFTER BACKSLASH
	MOVEI	T2,1		;A PHONY BYTE POINTER TO A NULL
	TLNE	U,LDLNEC	;ECHO OFF?
	JRST	RIDEL3		;YES. DON'T OUTPUT
>				;[arpa]
IFN FTCAFE&FT2741,<
	MOVEI	T3,LDR2741
	TDNE	T3,LDBDCH(U)
	JRST	RIDEL3
>

;CONTINUED ON NEXT PAGE
;HERE TO ECHO THE RUBOUT
	MOVE	T3,LDBDCH(U)	;IF ALREADY
	TDNN	T3,[LDLLCP,,LDRHLF] ;ECHOED, DON'T BUT DO UPDATE HPOS
	MOVE	T2,[POINT 9,[BYTE (9)210,0]]
	TLNN	P1,CHDEL	;RUBOUT OR BACKSPACE
	JRST	RIDEL4		;BACKSPACE (ECHO AS SELF)
	JUMPE	P3,RIDEL9	;A VIDEO TERMINAL?
	CAIE	P2,11		;A TAB?
	JRST	RIDEL7		;NO, ERASE 1 OR 2 CHARACTERS
	SCNOFF
	SKIPN	P1,LDBBKU(U)	;POSITION OF BREAK CHARACTER IN BUFFER
	MOVE	P1,LDBTIT(U)	;NONE, USE START OF THE BUFFER
	LDB	P2,PRPOS	;INITIALIZE CHARACTER COUNT
RIDELA:	CAMN	P1,LDBTIP(U)	;AT THE END?
	JRST	RIDELD		;YES
	LDCHK	T3,P1		;GET NEXT CHARACTER
	ANDI	T3,177		;JUST SEVEN BITS
	CAIE	T3,11		;A TAB?
	JRST	RIDELC		;NO
	TRZ	P2,7		;CLEAR LOW BITS
	ADDI	P2,10		;NEXT TAB STOP
	JRST	RIDELA		;LOOP OVER ALL CHARACTERS IN THE INPUT BUFFER
RIDELC:	MOVE	T1,CHTABL(T3)	;ECHO BITS
	TLNE	T1,CHUAE	;ECHO AS ↑X?
	ADDI	P2,1		;YES, COUNT IT AS 2 CHARACTERS
	AOJA	P2,RIDELA	;LOOP

;HERE WITH P2 = THE HORIZONTAL POSITION DUE TO TYPE IN

RIDELD:	SCNON
	PUSHJ	P,HPOS		;GET ACTUAL HORIZONTAL POSITION
	SUBI	T2,(P2)		;MINUS NUMBER OF CHARACTERS TYPED IN
	PUSHJ	P,BACKUP	;ADJUST HORIZONTAL POSITION
	JRST	RIDEL8		;ERASE BACK TO TAB STOP
RIDEL7:	MOVE	T1,CHTABL(P2)	;GET BITS TO CHECK FOR SPECIAL ECHOING
	MOVEI	T2,1		;ASSUME A SINGLE CHARACTER WAS ECHOED
	TLNE	T1,CHUAE	;REALLY ↑X ECHO?
	MOVEI	T2,2		;YES, ERASE 2 CHARACTERS
	PUSHJ	P,BACKUP	;ADJUST HORIZONTAL POSITION
RIDEL8:	MOVNI	T2,-10(T2)	;RELATIVE ADDRESS OF BYTE POINTER FOR ERASING
	TRNE	T2,-10		;LINE WRAP AROUND?
	MOVEI	T2,0		;NOT QUITE RIGHT BUT RIGHT IS HARD
	ADD	T2,P3		;ADDRESS OF BYTE POINTER FOR ERASING
	MOVE	T2,(T2)		;BYTE POINTER TO ERASE TABLE
	MOVEI	T1,0		;ZERO LDPSVC
	DPB	T1,LDPSVC	;SO CHARACTER DOESN'T GET ECHOED AGAIN
	JRST	RIDEL3		;GO ERASE THE CORRECT NUMBER OF CHARACTERS
RIDEL9:	MOVEI	T1,0
	MOVE	T3,LDBDCH(U)	;DIFFERENT FORMAT IF LOCAL COPY
	TDNN	T3,[LDLLCP,,LDRHLF]
	MOVSI	T1,L2LDEL	;WAS DELETE LAST CHARACTER TOO?
	TDNN	T1,LDBBY2(U)	;IF SO, DON'T OUTPUT ANOTHER BACKSLASH
	JRST	RIDEL0		;NO. GO SET UP A BACKSLASH
	MOVEI	T2,1		;PHONY BYTE POINTER
	JRST	RIDEL3		;GO STORE AND RETURN

RIDEL0:	IORM	T1,LDBBY2(U)	;STORE THAT THIS IS DELETE
	AOS	LDBHPS(U)	;COUNT BACKSLASH POSITION
	MOVE	T2,FLLBSP	;GET POINTER TO BACKSLASH
	JRST	RIDEL3		;GO STORE AND RETURN

RIDEL4:	MOVEI	T3,10		;UPDATE HPOS BY
	PUSHJ	P,ADJHP		; MINUS ONE
	PJRST	RIDEL3		;GO STORE AND RETURN

;SUBROUTINE TO ADJUST HORIZONTAL POSITION WHEN ERASING CHARACTERS
;CALL WITH T2 = NUMBER OF POSITIONS TO BACKUP, RETURNS CPOPJ, T2 INTACT

BACKUP:	PUSH	P,T2		;SAVE T2
	MOVEI	T3,10		;BACKSPACE
BACKU1:	PUSHJ	P,ADJHP		;BACKUP 1 CHARACTER
	SOJG	T2,BACKU1	;LOOP FOR ALL
	JRST	T2POPJ		;RESTORE T2 AND RETURN

;SUBROUTINE TO DETERMINE IF THE CURRENT TERMINAL IS A VIDEO TERMINAL
; I.E., SPECIFIED AS SUCH BY THE USER TYPING A TTY TYPE COMMAND
; RETURNS CPOPJ IF NOT, CPOPJ1 IF SO, T1 POINTS AT CHARACTERISTICS TABLE
; ENTRY FOR THE TERMINAL TYPE

TTVID:	MOVSI	T1,LDLLCP	;LOCAL COPY BIT
	TDZE	T1,LDBDCH(U)	;LINE DOING OWN ECHOING
	POPJ	P,		;YES, AVOID VIDEO STUFF (T1=0)
	LDB	T1,LDPTTT	;GET TERMINAL TYPE AS SET BY COMMAND
	JUMPE	T1,CPOPJ##	;GO IF NONE SPECIFIED
	TRZE	T1,100		;CUSTOMER DEFINED TERMINAL TYPE ?
	MOVNI	T1,(T1)		;YES, NEGATIVE TABLE INDEX
	LSH	T1,1		;2 WORDS PER ENTRY
	SKIPE	TCRTAB+1(T1)	;SKIP IF NOT A VIDEO TERMINAL
	AOS	(P)		;IT IS!
	POPJ	P,		;RETURN
RIDEL1:	SCNON
	JUMPN	P3,RIDELZ
	SKIPL	LDBDCH(U)	;IS OUTPUT IN PROGRESS?
	JRST	RIDELZ		;YES.  DISCARD RUBOUT OR CONTROL W
	MOVE	T2,FLLBSC	;BACKSLASH CRLF
RIFRET:	MOVSI	T1,L2LDEL	;INSIDE BACKSLASHES?
	TDNN	T1,LDBBY2(U)	; ..
	IBP	T2		;NO. SKIP BACKSLASH
	ANDCAM	T1,LDBBY2(U)	;NO LONGER IN BACKSLASHES
RIFRT1:	PUSHJ	P,SCNBOL	;SET BACK TO START OF LINE
RIDEL3:	PUSHJ	P,SETFLP	;SETUP THE FILLER POINTER
IFN FTLINK,<			;[link]
	PUSHJ	P,CHKLKF##	;[link] SEND FILL POINTER TO LINKS
>				;[link]
	PUSHJ	P,TOPOKE	;START OUTPUT IF NEEDED
RIDEL2:	JRST	RINUL		;NOW DISCARD RUBOUT

;HERE ON ANY OF THE THREE ALTMODES, TO DECIDE ON CONVERSION TO STDALT
RIALT:	PUSHJ	P,RIALTO
IFN FTCIMP,<			;[arpa]
	skipe	LDBIMP(U)	;[arpa] crosspatched out to arpanet?
	  JRST	RECI2A		;[arpa] yes.  send as image.
>				;[arpa]
	JRST	RECINA

RIALTO:	MOVEI	T2,(T3)		;GET A COPY OF THE CHAR.
	ANDI	T2,177		;ISOLATE CHAR (REMOVE PARITY/IMAGE/ECHO BITS)
	CAIN	T2,STDALT	;CHECK FOR TRUE ESC
	POPJ	P,
	MOVEI	T1,0		;NO, ASSUME DATA CHAR
	MOVSI	T2,LPLALT	;CONVERT OLD ALTMODES?
	TDNN	T2,LDBPAG(U)	;DO WE CONVERT OLD ALTMODES?
	JRST	RIALT2		;YES, SO GO DO IT
	TLNE	U,LDLLCT	;NO, BUT SHOULD WE CONVERT TTY UC?
	TRC	T3,240		;YES, SO CHANGE IT
	POPJ	P,		;ALL DONE
RIALT2:	MOVEI	T3,STDALT	;YES USE THE STANDARD ALTMODE
	MOVE	T1,CHTABL(T3)	;NOW A BREAK, SO GET ITS BITS
	POPJ	P,		;STORE WHATEVER THIS DECIDED ON

IFN FTSCLC,<

;RECEIVE INTERRUPT ROUTINE FOR LINE CONTROL TRANSACTIONS

;ENTER HERE FROM DEVICE-DEPENDENT ROUTINE WITH
;  TRANSACTION CODE IN T3,
;  PHYSICAL LINE # IN U (IDX FOR LINTAB, LDBDCH, ETC)
;    U'S RANGE CHECKED BY INTERRUPT ROUTINE
;  AC'S & PDL SETUP


LNCREC::MOVE	U,LINTAB##(U)
	CAIN	T3,LNTEHC	;DISPATCH ON CHARACTER CODE IN T3
	JRST	LNREHC		;ENABLE HUNG CHECK
	CAIE	T3,LNTDHC
	POPJ	P,		;ILLEGAL CODE--IGNORE

LNRDHC:	MOVEI	T3,LDRSHC	;DISABLE HUNG CHECK
	IORM	T3,LDBDCH(U)	;  TURN ON LDRSHC
	POPJ	P,

LNREHC:	MOVEI	T3,LDRSHC	;TURN OFF LDRSHC
	ANDCAM	T3,LDBDCH(U)
	POPJ	P,
> ;END OF IFN FTSCLC
IFN FTMODM,<			;CODE INCLUDED ONLY IF MODEMS SUPPORTED
;RECEIVE INTERRUPT ROUTINE FOR DATASET TRANSACTIONS

;ENTER HERE FROM DEVICE-DEPENDENT ROUTINE WITH TRANSACTION CODE IN
; T3, DSCTAB INDEX IN U, RANGE ALREADY CHECKED BY INTERRUPT
; ROUTINE, AC'S AND PDL SET UP.


DSCREC::MOVE	T2,DSCTAB##(U)	;GET TABLE ENTRY FIRST
	TLNE	T2,DSCBLI	;IGNORE INTERRUPTS?
	POPJ	P,0		;YES. DO SO.
IFN FTPI,<PUSHJ P,SIGDSC>	;SIGNAL, DATA SET STATUS CHANGE
	CAIN	T3,DSTRNG	;DISPATCH ON CODES
	JRST	DSRRNG		;RING FROM DATAPHONE
	CAIN	T3,DSTON	;CARRIER ON?
	JRST	DSRON		;YES.
IFN FTDIAL,<
	CAIN	T3,DSTPND	;DIALLER WANT ANOTHER DIGIT
	JRST	DSRPND		;YES
>
DSROFF:	CAIN	T3,DSTOFF	;OFF INTERRUPT?
	TLNN	T2,DSCHWC	;YES. DID I THINK HE WAS ON?
	POPJ	P,0		;NO. FORGET IT.
	TLNN	T2,DSCSWC	;DO I THINK HE SHOULD BE ON?
	JRST	DSROF1		;NO. JUST GO CLEAR HIM OUT.
	MOVEI	T1,5		;YES. TIME OUT IN CASE OF BRIEF FAILURE
	DPB	T1,DSTMPL	;STORE IN TIME BYTE.
	MOVSI	T1,DSCHWC	;CLEAR THE CARRIER BIT
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCFAI	;AND FLAG POSSIBLE FAILURE CONDITION
	IORM	T1,DSCTAB##(U)	; ..
	POPJ	P,0		;LET CLOCK TIME HIM OUT NOW.
DSROF1::MOVSI	T1,DSCHWC!DSCSWC!DSCIC2
	ANDCAM	T1,DSCTAB##(U)	;CLEAR ALL THESE BITS IN TABLE
IFN FTDIAL,<
	HRRZ	T1,DSCTAB##(U)	;GET TERMINAL NUMBER FOR THIS MODEM
	CAMN	T1,DSDUNI##	;DIALLER CODE USED BY IT?
	SETOM	TTYDDL##	;YES. CLEAR INTERLOCK TO FREE IT.
>
	MOVEI	T3,DSTOFF	;AND SEND OFF-COMMAND TO DEVICE
DSCCAL::MOVE	T2,DSCTAB##(U)	;T2 ← LINE NUMBER
	MOVEI	T1,ISRDSC	;DATASET CONTROL FUNCTION
	MOVE	T2,LINTAB##(T2)	;LDB ADDRESS
	PJRST	@LDBISR(T2)	;DISPATCH TO INTERUPT SERVICE

;SUBROUTINE TO SIGNAL DATA SET STATUS CHANGE
; ENTER T3=TRANSACTION CODE
IFN FTPI,<
SIGDSC::HRRZ	T1,LINTAB##(T2)	;GET LDB ADDRESS
	HRRZ	F,LDBDDB(T1)	;GET ADDRESS OF DDB
	MOVE	T4,J		;SAVE J
	JUMPE	F,SIGDS1	;ALL DONE IF ZERO
	LDB	J,PJOBN##	;GET JOB NUMBER
	JUMPE	J,SIGDS1	;JUMP IF JOB 0 (CAN THAT HAPPEN?)
	SIGNAL	C$DSET
	  JFCL
SIGDS1:	MOVE	J,T4		;RESTORE J
	POPJ	P,		;RETURN
> ;END IFN FTPI
;STILL IN FTMODM
DSRON:
IFN FTDIAL,<
	TLNN	T2,DSCDLW	;IN DIALLER WAIT?
	JRST	DSRON1		;NO.
	MOVSI	T1,DSCDLW!DSCEON	;YES. CLEAR FLAGS FOR DIALLER
	ANDCAM	T1,DSCTAB##(U)	;IN TABLE IN CORE
	SETOM	TTYDDL##	;FREE UP DIALLER CODE
	MOVSI	T1,DSCDLC	;SET SUCCESSFUL COMPLETION BIT
	IORB	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
	PUSH	P,T2		;SAVE OLD STATUS
	PUSHJ	P,DSCWAK	;WAKE THE JOB, IF ANY STILL THERE.
	POP	P,T2		;RESTORE OLD BITS
> ;END IFN FTDIAL
DSRON1:
IFN FTCAFE,< ;CAFE'S SAY HELLO AFTER AUTOMATIC BAUD DETECT EVEN ON
;		LOCAL LINES. THIS ALLOWS USER TO GET SIGN ON MESSAGE
	HRRZ	T1,DSCTAB##(U)	;GET REAL LINE NUMBER
	HRRZ	T1,LINTAB##(T1)	;GET ADDRESS OF LDB
	MOVE	T1,LDBDCH(T1)	;GET DEVICE BITS
	TRNN	T1,LDRDSD	;IS THIS A REAL DATASET LINE?
	JRST	DSRON2		;NO--LOCAL TERMINAL JUST CAME UP
> ;END FTCAFE
	TLNE	T2,DSCHWC	;HE CAME ON. IS THAT NEWS TO ME?
	POPJ	P,0		;I THOUGHT HE WAS ON. FORGET IT.
	TLNN	T2,DSCSWC	;DO I WANT HIM ON?
	JRST	DSROF1		;NO. GO FORCE HIM OFF.
IFN FTGPO2B,<
	TLNE	T2,DSCFAI+DSCDLW	;A GPO2B MODEM CANNOT BE ALLOWED
	POPJ	P,		;TO RECOVER UNTIL THE TIMEOUT HAS
				;OCCURRED TO FORCE DETACH
				;BECAUSE 2B'S GENERATE SPURIOUS CARRIER
				;FROM DIAL TONE, BUSY, ETC.
>

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

	MOVSI	T1,DSCTMM+DSCFAI;YES. CLEAR TIME AND FAILURE BITS
	ANDCAM	T1,DSCTAB##(U)	;IN THE TABLE (STILL IN T2)
	MOVSI	T1,DSCHWC	;MARK THAT HE CAME ON
	IORM	T1,DSCTAB##(U)	;IN TABLE
	TLNE	T2,DSCFAI+DSCDLW;WAS ALL THIS A BRIEF FAILURE?
	POPJ	P,0		;YES. JUST DISMISS, HE'S BACK.
	MOVSI	T1,DSCBLI+DSCNCR;NO. NEW GUY. SET BLIND AND DELAY BITS
	HRRZ	F,LINTAB##(T2)	;LDB
	HRRZ	F,LDBDDB(F)	;DDB
	JUMPE	F,DSRN1A	;GO IF NO DDB
	MOVE	T4,DEVMOD(F)	;CHARACTERS
	TLNN	T4,TTYATC	;IF CONSOLE
	TRNN	T4,ASSCON!ASSPRG;AND NOT ASSIGNED
DSRN1A:	TLO	T1,↑D60		;SET TIME OUT
	IORM	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
DSRON2:	HRRZ	U,LINTAB##(T2)	;GET LDB ADDRESS FOR LINE
	PUSHJ	P,TSETBI	;CLEAR INPUT BUFFER
IFN FTNET,<
	MOVE	T1,LDBREM(U)	;GET THE REMOTE BITS
	TLNE	T1,LRLVTM	;  AND IF THIS IS A VTM LINE,
	PUSHJ	P,VTMDSO##	;  TURN CARRIER AND QUEUE LINE FOR SERVICE
>
	MOVSI	T1,L1LOFL
	ANDCAM	T1,LDBOFL(U)
	SKIPGE	DEBUGF##
	POPJ	P,
	HRRZ	F,LDBDDB(U)	;GET DDB
	JUMPN	F,CPOPJ##	;DO NOT RUN INITIA IF THERE IS A
				; JOB ON THE LINE
	MOVEI	T1,TTFCXH	;GET HELLO COMMAND INDEX
	JRST	TTFORC		;FORCE HELLO COMMAND
> ;END CONDITIONAL ON FTMODM
TTFRC1:	AOS	(P)
TTFORC::DPB	T1,LDPCMX	;STORE FORCED COMMAND INDEX
	MOVSI	T1,LDBCMR+LDBCMF;FORCED COMMAND REQUEST.
	JRST	COMST1		;SET COMMAND COUNT, IF NEEDED

IFN FTMODM,<
DSRRNG:	MOVE	T1,STATES##	;PHONE RINGING. MAY I ANSWER?
	TRNE	T1,ST.NRL	;CHECK THE SCHEDULE COMMAND WORD
	POPJ	P,0		;NOT ALLOWED. IGNORE.
	PUSH	P,U		;SAVE PTR TO DSCTAB
	HRRZ	U,DSCTAB##(U)	;GET REAL LINE NUMBER
	HRRZ	U,LINTAB##(U)	;GET ADR OF LDB
IFN FTCAFE,<
	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNN	T1,LDRDSD	;IS THIS A DATASET LINE?
	JRST	UPOPJ##		;NO
>;END OF IFN FTCAFE
	HRRZ	F,LDBDDB(U)	;DDB PTR
	JUMPE	F,DSRRN2	;NO JOB, ALL OK
	MOVE	T1,DEVMOD(F)	;DEVICE BITS
	TLNN	T1,TTYATC	;CONTROLLING TTY?
	JRST	DSRRN2		;NO, SO NO JOB
				;IF WE GET HERE, WE HAVE RING ON LINE
				; WITH A JOB, WHICH IS NOT SUPPOSED TO
				; HAPPEN.  TO PREVENT SECURITY PROBLEMS,
				; WE DETATCH THE JOB
	PUSHJ	P,DSCDET	;DETACH OR KILL IF NOT LOGGED IN.
DSRRN2:	POP	P,U		;RESTORE DSCTAB PTR
	MOVEI	T3,0		;CLEAR VARIOUS
	DPB	T3,DSTMPL	; TIMERS
	MOVSI	T1,DSCFAI+DSCTMM;CLEAR THE MOMENTARY FAILURE BIT
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCSWC+↑D30	;TURN ON ALLOW BIT, AND TIME.
DSRRN1:	IORM	T1,DSCTAB##(U)	;IN DATASET CONTROL TABLE
	MOVEI	T3,DSTON	;SEND A TURN-ON COMMAND TO DEVICE-
	PJRST	DSCCAL		; DEPENDENT ROUTINE, AND DISMISS


DSCDET:	MOVEI	T1,TTFCXD	;DO THE DETACH BY
	PJRST	TTFORC		; FORCING A .BYE
IFN FTDIAL,<
DSRPND:	TLNE	T2,DSCEON	;SENT ALL DIGITS?
	POPJ	P,0		;YES. IGNORE REQUEST
	MOVEI	T1,↑D60		;ONE MINUTE FROM SENDING DIGIT
	DPB	T1,DSTMPL	;INTO TIME-OUT OF DATASET
	MOVSI	T1,DSCEON	;FLAG END OF NUMBER SENT, IF TRUE.
	ILDB	T3,TTYDDA##	;GET ANOTHER DIGIT
	CAIN	T3,17		;END OF NUMBER CODE?
	JRST	DSRPN1		;YES
	ADDI	T3,DSTPND	;CONVERT TO TRANSACTION CODE FOR XXXINT
	PJRST	DSCCAL		;AND SEND IT OUT
	

DSRPN1:	IORM	T1,DSCTAB##(U)	;SET FLAG IN TABLE
	POPJ	P,0		;DON'T SEND NUMBER
> ;END OF FTDIAL
> ;END OF FTMODM CONDITIONAL

IFE FTMODM,<DSCREC==:CPOPJ##>
	SUBTTL	KI10 CONSOLE TERMINAL SERVICE

IFN FTKI10,<
CTYINT::CONSO	TTY,40		;INPUT OR OUTPUT
	JRST	CTYOUT		;OUTPUT.
CTYIN:	DATAI	CTY,T3		;INPUT. GET THE CHARACTER
	JRST	RECINT		;GO PROCESS IT

CTYOUT:	CONO	CTY,200+SCNCHN##	;CLEAR THE OUTPUT BIT
	JRST	XMTINT		;AND GO SERVICE INTERRUPT
>;END IFN FTKI10
	SUBTTL	KS10 CTY AND KLINIK TERMINAL SERVICE

IFN FTKS10,<
CT0INT::SKIPN	.CPFEF##	;HAS FRONT END INTERRUPTED ?
	JRST	.-1		;ON THROUGH SKIP CHAIN
	WRPI	CLRCTY##	;CLEAR THE INTERRUPT
	SETZM	.CPFEF##	;CLEAR THE FLAG
	JSR	SCNSAV##	;SAVE AC'S ETC.
	MOVE	T3,KLIIWD	;GET KLINIK INPUT WORD
	TRNN	T3,KLIIVL	;IS THERE INPUT?
	  JRST	CTYIN1		;NO--PROCEED
	SETZM	KLIIWD		;YES--CLEAR IT
	MOVEI	U,KLILIN##	;GET KLINIK LINE NUMBER
	PUSHJ 	P,RECINT	;PASS TO SCNSER
CTYIN1:	MOVE	U,LINTAB+KLILIN## ;LDB FOR KLINIK LINE
	SKIPL	LDBDCH(U)	;IS KLINIK OUTPUT ACTIVE?
	SKIPE	KLIOWD		;YES--IS OUTPUT WORD AVAILABLE?
	JRST	CTYIN2		;NO--PROCEED
	MOVEI	U,KLILIN##	;KLINIK LINE NUMBER
	PUSHJ	P,XMTINT	;SEE IF MORE TO TYPE
CTYIN2:	SKIPN	T3,CTYIWD	;ANY CTY INPUT?
	  JRST	CTYIN3		;NO--PROCEED
	SETZM	CTYIWD		;YES--CLEAR IT
	MOVEI	U,CTYLIN##	;CTY LINE NUMBER
	PUSHJ	P,RECINT	;PASS TO SCNSER
CTYIN3:	MOVE	U,LINTAB+CTYLIN## ;GET LDB ADR FOR CTY
	SKIPL	LDBDCH(U)	;IS CTY TYPING ?
	SKIPE	CTYOWD		;AND IS OUTPUT WORD FREE ?
	JRST	CTYIN4		;NOT TYPING OR STILL BUSY
	MOVEI	U,CTYLIN##	;LINE NUMBER FOR CTY
	PUSHJ	P,XMTINT	;TRY TO TYPE MORE STUFF
CTYIN4:	POPJ	P,		;RETURN
>;END IFN FTKS10
	SUBTTL	FILLERS AND SIMULATION ROUTINES

;ROUTINE TO SET UP FILLERS FOR OUTPUT CHARACTERS
;CALL WITH
;	MOVE	T3,CHARACTER
;	MOVE	T1,CHTABL(T3)
;	PUSHJ	P,SETFLO
;	  <CHARACTER NEEDS FILLERS, ALREADY SETUP>
;	<CHARACTER NEEDS NO FILL>


SETFLO:	TLZ	T1,CHUAE+CHALT+CHCRE	;THESE ECHO MODES NOT USED ON OUTPUT
	TLO	T1,CHFILO	;FLAG OUTPUT-FILLER REQUEST
	JRST	SETFL2		;REST OF ROUTINE SAME AS ON INPUT

;ROUTINE TO SET FILLER POINTER FOR INPUT CHARACTERS (ECHOING)

SETFLI:	TLNE	T1,CHALT	;IS THIS A POSSIBLE ALTMODE?
	PUSHJ	P,RIALTO	;YES, SEE IF IT IS A REAL ALTMODE
IFN FTCAFE,<
IFN FT2741,<
	MOVE	T2,LDBDCH(U)	;IS THIS A 2741
	TRNE	T2,LDR2741	; ??
	JRST	CPOPJ1##	;YES--FILLERS DONE BY PDP-11
> ;END FT2741
> ;END FTCAFE

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;COMMON CODE FOR SETFLI/SETFLO

SETFL2:	MOVE	T2,LDBHPS(U)	;GET HORIZONTAL POSITION COUNTER
	TLNE	U,LDLDLR	;USER WANT DOLLAR SUPPRESSED?
	TLZ	T1,CHALT+CHUAE+CHCRE	;YES. DO SO.
	TLNE	T1,CHUAE	;WILL ↑X BE ADDED?
	ADDI	T2,2		;YES. ADD 2 TO HPOS
	TLNE	T1,CHALT	;IS IT GETTING A DOLLARSIGN?
	ADDI	T2,1		;YES. COUNT IT.
	JUMPLE	T2,SETFI1	;IF NOT AT END OF SCREEN
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] IF CROSSPATCHED, NO FREE CRLF
>				;[arpa]
	PUSHJ	P,PTBTCH##	;CHECK FOR REGULAR PTY
	  JRST	SETFI1		;IT IS, NO FREE CRLF
	MOVE	T2,LDBDCH(U)	;GET THE CHARACTERISTICS WORD
	TLNE	T2,LDLNFC	;USER WANT FREE <CR><LF>?
	JRST	SETFI1		;NO. FORGET IT.
;	PJRST	SETCRF		;YES, FALL INTO SETCRF

;SETCRF -- ROUTINE TO SETUP A FREE CRLF POINTER

SETCRF:	PUSHJ	P,SCNBOL	;RESET LINE COUNTERS IN ANY CASE
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] IF CROSSPATCHED, NO FREE CRLF
>				;[arpa]
	TRNE	T2,LDRREM	;IS THIS A NETWORK VIRTUAL TERMINAL?
	JRST	SETCR5		;YES, THEN NO FILLER (THE REMOTE COMPUTER
				; WILL SUPPLY THE FREE <CR><LF>, WE NEED
				; MERELY NOTE THAT A NEW LINE IS STARTING)
	LDB	T2,LDPFLC	;GET FILL CLASS
SETCR2:	MOVE	T2,FLLCRP(T2)	;GET APPROPRIATE POINTER TO STRING
	PUSHJ	P,SETFLP	;SETUP THE APPROPRIATE FILLER POINTER
	MOVSI	T2,LDLLCP	;DON'T ECHO INPUT CHARACTER AFTER FREE CRLF
	TLNN	T1,CHFILO	; BUT IF OUTPUT, DON'T EAT A CHARACTER
	TDNN	T2,LDBDCH(U)	;IF LOCAL COPY IS SET
	DPB	T3,LDPSVC	;SAVE CHARACTER FOR LATER
	POPJ	P,		;NON-SKIP RETURN (NEEDED CRLF)

SETCR5:	MOVE	T2,T3		;SCRATCH COPY OF CHARACTER
	ANDI	T2,177		;JUST SEVEN-BIT ASCII
	CAIL	T2,40		;IS CHARACTER A
	CAIL	T2,177		; NORMAL PRINTING ASCII GRAPHIC?
	TLNE	T1,CHALT!CHUAE	;NO, CONTROL, IF EITHER "$" OR "↑X" FORM
	AOS	LDBHPS(U)	;THEN COUNTS AS A PRINTING CHARACTER
	TLNE	T1,CHUAE	;IN ADDITION, IF "↑X" FORM
	AOS	LDBHPS(U)	; THEN COUNTS AS TWO PRINTING CHARACTERS
	PUSHJ	P,INCPCT	;COUNT LINES OUTPUT FOR TTY PAGE N
	HLL	U,LDBDCH(U)	;GET LEFT-HALF CHARACTERISTICS
	TLNN	U,LDLSSO	;DID INCPCT HIT A PAGE BREAK?
	JRST	CPOPJ1##	;NO, JUST OUTPUT THE FIRST CHARACTER

;HERE IF THE FREE <CR><LF> THAT WE KNOW THE REMOTE IS ABOUT TO OUTPUT
;(AS SOON AS IT SEES THE CHARACTER IN T3) WILL ALSO BREAK THE PAGE LIMIT.
;WE MUST SUPPLY THE FREE <CR><LF> AND THEN STOP IN ORDER TO MAKE THE
;REMOTE BEHAVE THE SAME AS LOCALLY-OWNED TERMINALS. THIS RELYS ON THE
;FACT THAT XMTSPC WILL FORCE OUT THE FILLER POINTER EVEN IF THE LINE
;IS XOFFED - A DUBIOUS FEATURE AT BEST.

	PUSHJ	P,SCNBOL	;OOPS - RE-CLEAR HORIZONTAL POSITION

;TECHNICALLY, INCPCT SHOULD BE UNDONE, SINCE THE <CR><LF> COMING WILL
;LEAVE IT OFF BY ONE, BUT THE XON NEEDED TO GET OUT OF THE STUCK STATE
;WILL RESET THE PAGE COUNTER, SO . . .

	MOVEI	T2,4		;FILLER POINTER WITH BELL
				;SEE SETCR2
	JRST	SETCR2		;GO OUTPUT A NEW LINE
SETFI1:	TLNN	T1,CHFIL	;THIS CHAR NEED FILLERS?
	JRST	SETFI2		;NO.
SETFI0:	PUSH	P,T3		;SAVE THE CHARACTER
				;*** CHAR MUST BE AT 0(P) FOR SIMULATORS ***
				;*** EVEN THOUGH THIS IS BAD PRACTICE
IFN FT2741&FTCAFE,<
	MOVE	T3,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TRNE	T3,LDR2741	;IS THIS A 2741?
	  JRST	ZFLPOP		;YES - DC76 WILL DO FILLERS
	MOVE	T3,(P)
>;END OF IFN FT2741&FTCAFE
	ANDI	T3,177		;JUST 7 BITS (NO PARITY)
	CAIG	T3,15		;NEED TO CALL ROUTINE FOR IT?
	JRST	@SETFLD-10(T3)	;YES. GO DO IT.
	CAIL	T3,21		;CONTROL Q THRU T?
	JRST	SETFI6		;YES. THEY HAVE SPECIAL HANDLERS TOO
	PUSHJ	P,SETFLC	;GET FILL CLASS
	JUMPE	T2,ZFLPOP	;NO. USER WANT FILLER SUPPRESSED?
	SKIPA	T2,FILLP1	;NO. ASSUME ONE FILLER IS ENOUGH
ZFLPOP:	MOVEI	T2,0		;POINTER FOR NO FILLERS
FLLPOP:	PUSHJ	P,SETFLP	;SETUP THE FILLER POINTER
	AOS	-1(P)		;RESTORE CHARACTER AND SKIP RETURN
	JRST	T3POPJ##	;SKIP IS BECAUSE T3 IS TO BE TYPED
				; SKIP IS BECAUSE T3 IS TO BE TYPED

SETFI2:	TLNN	T1,CHUAE+CHALT+CHCRE	;ECHO AS ↑X OR $ ?
	JRST	CPOPJ1##	;NO. NOTHING SPECIAL. JUST SEND.
	TLNE	T1,CHALT	;ALTMODE?
	JRST	SETFI3		;YES.
	TLNE	T1,CHCRE	;ECHO AS UPARROW X CRLF?
	JRST	SETFI4		;YES.
	TRC	T3,300		;TURN ON 100 BIT, COMPLEMENT PARITY
	DPB	T3,LDPSVC	;STORE FOR AFTER THE UPARROW
	SKIPA	T2,FLLUPA	;GET POINTER TO UPARROW CONST

SETFI3:	MOVE	T2,FLLDLR	;GET POINTER TO DOLLARSIGN GRAPHIC
	AOS	LDBHPS(U)	;ADVANCE HORIZONTAL POSITION
	PJRST	SETFLP		;SET FILLER POINTER AND RETURN
;CAN ONLY GET HERE FOR ↑U,↑Z OR ↑C. OTHERS NOT STORED IN INPUT BUFFER

SETFI4:	ANDI	T3,177		;NO PARITY
	PUSHJ	P,SCNBOL	;SET COUNTERS BACK TO BEGINNING OF LINE
	MOVEI	T2,0		;0 BYTE POINTER
	CAIN	T3,"C"-100	;CONTROL C?
	MOVE	T2,FILXCP	;YES. ITS POINTER
	CAIN	T3,"Z"-100	;CONTROL Z?
	MOVE	T2,FILXZP	;YES. ITS POINTER
	IBP	T2		;SKIP BACKSLASH
	PJRST	SETFLP		;STORE ECHO POINTER AND FORCE IT OUT

SETFI6:	TLNN	U,LDLDLR	;ECHOING GRAPHICS INHIBITED?
	TLNE	T1,CHFILO	;IS THIS FOR INPUT OR OUTPUT OF ↑Q-↑T?
	JRST	SETFI7		;NO GRAPHICS. JUST THROW ON A RUBOUT.
	MOVEI	T2,2		;LENGTH OF PRINT REPRESENTATION
	ADDM	T2,LDBHPS(U)	;ADD TO HORIZONTAL POSITION COUNTER
	MOVE	T2,STFLT2-21(T3);GET ECHO POINTER FOR CONTROL Q-T
	SOS	-1(P)		;NON-SKIP RETURN
	JRST	FLLPOP		;STORE FILLER AND RETURN

SETFI7:	PUSHJ	P,SETFLC	;GET FILL CLASS
	SKIPE	T2		;FILL 0?
	MOVE	T2,FILLP1	;NO, USE A FILLER
	PJRST	FLLPOP		;STORE FILLER AND GO HOME
;SETFLC -- ROUTINE TO SETUP THE FILLER CLASS FOR A LINE

SETFLC:	
IFN FTNET,<
	MOVEI	T2,LDRREM	;REMOTE BIT
	TDNE	T2,LDBDCH(U)	;REMOTE STATION DOES ITS OWN FILL
	TDZA	T2,T2		;SO RETURN INDEX OF ZERO
>
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] IF CROSSPATCHED, let remote fill.
>				;[arpa]
	PUSHJ	P,PTBTCH##	;CHECK FOR REGULAR PTY
	  TDZA	T2,T2		;IT IS, USE FILLER CLASS 0
	LDB	T2,LDPFLC	;ELSE GET FILL CLASS FROM LDB
	POPJ	P,		; AND RETURN



;ROUTINE TO SETUP AN "XON CLASS" FILLER POINTER
;CALL
;	MOVE	T2,FILL POINTER
;	PUSHJ	P,SETXNP
;	<ALWAYS RETURN HERE>

SETXNP::SCNOFF			;GET SCNSER INTERLOCK
	MOVEM	T2,LDBXNP(U)	;STORE FILL POINTER
	PJRST	SETFP1		;SET LDLFCP & RETURN



;ROUTINE TO SETUP A FILLER POINTER. SETS LDLFCP IF APPROPRIATE.
;CALL
;	MOVE	T2,FILLER POINTER
;	PUSHJ	P,SETFLP
;	<ALWAYS RETURNS HERE>
;ENTER AT SETFPT IF SCNOFF

SETFLP::SCNOFF
SETFPT::MOVEM	T2,LDBFLP(U)	;STORE IN LINE BLOCK
	JUMPE	T2,SONPPJ	;CLEARED WORD, JUST RETURN
SETFP1:	MOVSI	T2,LDLFCP
	IORM	T2,LDBDCH(U)	;SET FLAG FOR XMTCHR
	JRST	SONPPJ		;NON-SKIP RETURN, TO FORCE OUT
;DISPATCH TO SET FILLERS FOR SOME CHARACTERS

SETFLD:	EXP	FILLH,FILLI,FILLJ,FILLK,FILLL,FILLM
;POINTERS, CODE AND DATA FOR FILLER CHARACTERS

;HERE FOR A BACKSPACE AND HARDWARE VERTICAL TAB

FILLH:
FILLK2:	PUSHJ	P,SETFLC	;GET FILLER CLASS FOR LINE
	MOVE	T2,FILLHP(T2)	;GET FILLER BYTE POINTER
	JRST	FLLPOP		;GO STORE AND RETURN.

FLLFLG==:1				;FLAG TO ADD A CRLF AFTER THIS FILLER

FILXCP:	POINT	9,FILXCD	;CONTROL C ECHO
FILXCD:	BYTE	(9) 134,336,303,FLLFLG	;BACKSLASH, ↑C CRLF
FILXUP:	POINT	9,FILXUD	;CONTROL U ECHO
FILXUD:	BYTE	(9) 134,336,125,FLLFLG	;BACKSLASH, ↑U CRLF
FILXOP:	POINT	9,FILXOD	;CONTROL O ECHO
FILXOD:	BYTE	(9) 134,336,317,FLLFLG	;BACKSLASH, ↑O CRLF
FILXZP:	POINT	9,FILXZD	;POINTER TO CONTROL Z ECHO
FILXZD:	BYTE	(9) 134,336,132,FLLFLG	;BACKSLASH, ↑Z CRLF

;DISPATCH FOR ↑Q TO ↑T ECHOES

STFLT2:	POINT	9,FILXQD
	POINT	9,FILXRD
	POINT	9,FILXSD
	POINT	9,FILXTD

FILXQD:	BYTE	(9) 336,321,21,377,0	;↑Q
FILXRD:	BYTE	(9) 336,322,22,377,0	;↑R
FILXSD:	BYTE	(9) 223,336,123,0	;↑S
FILXTD:	BYTE	(9) 24,336,324,0	;↑T
FILLKP:					;POINTERS FOR BS AND VT
FILLHP:	0				;NO FILLERS
FILLP2:	POINT	9,FILLRZ,8	;2 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS

FILLLP:					;POINTERS FOR FORMFEED
	0				;NO FILLERS
	POINT	9,FILLRX,26	;12 FILLERS
	POINT	9,FILLER,17	;21 FILLERS
	POINT	9,FILLER,17	;21 FILLERS

FILLJP:					;POINTERS FOR LINEFEED
	0				;NO FILLERS
FILLP1:	POINT	9,FILLRZ,17	;1 FILLER
	POINT	9,FILLRY,8	;6 FILLERS
	POINT	9,FILLRY,8	;6 FILLERS

FLLCRP::POINT	9,FLLCR0	;TABLE OF POINTERS FOR FREE CRLF'S
	POINT	9,FLLCR1
	POINT	9,FLLCR2
	POINT	9,FLLCR2

	POINT	9,FLLCR3
FLLCR0:	BYTE	(9) 215,12,0	;DATA FOR FREE CRLF'S
FLLCR1:	BYTE	(9) 215,215,12,377,0
FLLCR2:	BYTE	(9) 215,215,12,377,377,377,377,377,0

FLLCR3:	BYTE	(9) 215,12,207,0
FLLUPA:	POINT	9,FLLUP1	;POINTER TO UPARROW
FLLDLR:	POINT	9,FLLUP1,17	;POINTER TO DOLLARSIGN
FLLUP1:	BYTE	(9) 336,0,44,0	;UPARROW AND $, WITH PARITY
FLLBSP:	POINT	9,FLLBS1	;POINTER TO BACKSLASH
FLLBS1:	BYTE	(9) 134,0,134,FLLFLG	;BACKSLASH DATA
FLLBSC:	POINT	9,FLLBS1,17	;POINTER TO BACKSLASH - CRLF

FLLCOP:	0				;FILLERS FOR OUTPUT CR
	POINT	9,FLLCO1,17	;ONE EXTRA CR
	POINT	9,FLLCO1
	POINT	9,FLLCO1
FLLCO1:
;[dm1500]BYTE	(9) 215,215,215,0	;EXTRA CARRIAGE RETURNS
	BYTE	(9) 377,377,377,0	;[dm1500] fill with rubouts: some
					;[dm1500]  terminals (datamedia's)
					;[dm1500]  add <LF> to <CR>.

;DUMMY FILLER

FLLDMY:	BYTE(9)	0,0,0,0
FLLDMP:	POINT	9,FLLDMY
VT06BP:	POINT	9,VT06TB
	POINT	9,VT06TB+2,8
	POINT	9,VT06TB+4,17
	POINT	9,VT06TB+6,26
	POINT	9,VT06TB+10,35
	POINT	9,VT06TB+13,8
	POINT	9,VT06TB+15,17
	POINT	9,VT06TB+17,26

VT06EP:	POINT	9,VT06EL
	POINT	9,VT06E1
	POINT	9,VT06E2
	POINT	9,VT06E3

VTXXBP:	POINT	9,VTXXTB
	POINT	9,VTXXTB,26
	POINT	9,VTXXTB+1,17
	POINT	9,VTXXTB+2,8
	POINT	9,VTXXTB+2,35
	POINT	9,VTXXTB+3,26
	POINT	9,VTXXTB+4,17
	POINT	9,VTXXTB+5,8

VTXXEP:	POINT	9,VTXXEL
	POINT	9,VTXXE1
	POINT	9,VTXXE2
	POINT	9,VTXXE3

V100EP:	POINT	9,VTXXEL
	POINT	9,V100E1
	POINT	9,V100E2
	POINT	9,V100E3

;[hp2621]  HP2621 terminal support
HP26EP: POINT	9,VTXXEL	;[hp2621]
	POINT	9,HP26E1	;[hp2621]
	POINT	9,HP26E2	;[hp2621]
	POINT	9,HP26E3	;[hp2621]

;[dm1500] data media 1500 support terminal support
DM15EP:	POINT	9,VTXXEL	;[dm1500]
	POINT	9,DM15E1	;[dm1500]
	POINT	9,DM15E2	;[dm1500]
	POINT	9,DM15E3	;[dm1500]
VT06TB:	BYTE	(9)	377,377,377,210,240,377,377,377
	BYTE	(9)	210,377,377,377,210,240,377,377
	BYTE	(9)	377,210,377,377,377,210,240,377
	BYTE	(9)	377,377,210,377,377,377,210,240
	BYTE	(9)	377,377,377,210,377,377,377,210
	BYTE	(9)	240,377,377,377,210,377,377,377
	BYTE	(9)	210,240,377,377,377,210,377,377
	BYTE	(9)	377,210,240,377,377,377,210,377
	BYTE	(9)	377,377,210,240,377,377,377,210
	BYTE	(9)	0

VT06EL:	BYTE	(9)	215,377,377,377,0
VT06E1:	BYTE	(9)	30,377,377,377,0
VT06E2:	BYTE	(9)	30,377,377,377,36,377,377,377,0
VT06E3:	BYTE	(9)	215,377,377,377,36,377,377,377,0

VTXXTB:	BYTE	(9)	210,240,210,210,240,210,210,240
	BYTE	(9)	210,210,240,210,210,240,210,210
	BYTE	(9)	240,210,210,240,210,210,240,210
	BYTE	(9)	0

VTXXEL:	BYTE	(9)	215,0
VTXXE1:	BYTE	(9)	33,303,0
VTXXE2:	BYTE	(9)	33,303,33,113,0
VTXXE3:	BYTE	(9)	215,33,113,0

V100E1:	BYTE	(9)	33,333,303,0
V100E2:	BYTE	(9)	33,333,303,33,333,113,0
V100E3:	BYTE	(9)	215,33,333,113,0

;[hp2621] HP2621 terminal support
;[hp2621] 215 = cr / <esc>C = forward cursor /<esc>K  = erase EOL

HP26E1:	BYTE	(9)	33,103,0		;[hp2621] forward one
HP26E2:	BYTE	(9)	33,103,33,113,0		;[hp2621] forward, erase line
HP26E3:	BYTE	(9)	215,33,113,0		;[hp2621] erase entire line

;[dm1500] data media terminal support
;[dm1500] 215 = <cr> /234 = forward cursor / 35 = erase EOL

DM15E1:	BYTE	(9)	234,0		;[dm1500] forward one
DM15E2:	BYTE	(9)	234,35,0	;[dm1500] forward, erase line
DM15E3:	BYTE	(9)	215,35,0	;[dm1500] erase entire line
;HERE TO GENERATE FILLERS OR SIMULATION FOR HORIZONTAL TAB
;PHPOS IS UPDATED ALREADY, BUT POHPOS HAS THE PREVIOUS POSITION,
;LOW ORDER THREE BITS, SO THE TAB SIMULATION CAN BE DONE FROM IT.

FILLI:
IFN FTNET,<
	MOVEI	T2,LDRREM	;REMOTE BIT
	TDNE	T2,LDBDCH(U)	;REMOTE STATION DOES OWN FILL
	JRST	ZFLPOP		;SO NO FILLERS
>
	PUSHJ	P,SETFLC	;GET FILLER CLASS
	TLNN	U,LDLTAB	;USE TAB, OR MAKE IT OUT OF SPACES?
	JRST	FILLI1		;SPACES.
	TRNN	T2,1		;FILL CLASS 0 OR 2?
	JRST	ZFLPOP		;YES, NO FILLERS
	LDB	T1,POHPOS	;GET OLD POSITION ON LINE.
	MOVE	T2,FILLP2	; ASSUME UNDER HALFWAY TO TAB STOP
	TRNE	T1,4		;TRUE?
FILL1:	MOVE	T2,FILLP1	;NO. NEED JUST ONE FILLERS.
	JRST	FLLPOP		;GO STORE FILLER POINTER, SEND
				; TAB, AND RETURN.

;HERE TO MAKE A TAB OUT OF SOME SPACES.

FILLI1:	MOVEI	T3,640		;WILL USE SPACES. DISCARD SAVED
				; TAB ON STACK.
				; IMAGE BIT BECAUSE HPOS NOW RIGHT
	LDB	T1,POHPOS	;GET LOW 3 BITS OF OLD HPOS
	MOVE	T2,FILLIP(T1)	;GET CORRESPONDING POINTER TO SPACES
	JRST	SCCHPJ		;GO STORE, TYPE FILLERS AND SVC
				; AND RETURN.

FILLJ:
	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FILLJP(T2)	;GET THE CORRESPONDING FILLERS
	JRST	FLLPOP		;FOR A LINEFEED, AND RETURN.

FILLK:	TLNE	U,LDLFRM	;THIS LINE HAVE FORM MOTION?
	JRST	FILLK2		;YES. USE SAME FILLERS AS BACKSPACE
	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FLLKSP(T2)	;GET SIMULATION POINTER
FILLK1:	MOVEI	T3,12		;CLOBBER THE VT OR FF ON STACK
SCCHPJ:	DPB	T3,LDPSVC	;SAVE CHARACTER FOR AFTER FILLERS
	PUSHJ	P,SETFLP	;SETUP THE FILLER POINTER
	JRST	T3POPJ##	;AND NON-SKIP RETURN TO CAUSE FILLERS
FILLL:	TLNE	U,LDLFRM	;THIS LINE HAVE FORM MOTION?
	JRST	FILLL1		;YES. GO SET FILLERS.
	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FLLLSP(T2)	;GET POINTER TO LINEFEEDS AND FILLERS
	JRST	FILLK1		;GO TO COMMON CODE

FILLL1:	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FILLLP(T2)	;AND FILLER POINTER
	JRST	FLLPOP		;GO STORE THIS POINTER AND RETURN

FILLM:	TLNE	T1,CHFILO	;NO, IS THIS FOR IN OR OUTPUT?
	JRST	FILLM1		;OUTPUT.
	MOVEI	T2,L2RXON	;XON BIT
	TDNE	T2,LDBBY2(U)	;XON IN EFFECT?
	JRST	ZFLPOP		;NO LOCAL, OR XON TRUE. THEREFORE,
	MOVE	T2,LDBDCH(U)	;GET DCH BITS BACK
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] CROSSPATCHED?
	 TRNE	T2,LDRIMP	;[arpa] OR AN IMP?
	  JRST	ZFLPOP		;[arpa] YES, LET REMOTE DO IT
>				;[arpa]
	TDNN	T2,[XWD LDLLCP,LDRHLF]	;EITHER TYPE OF LOCAL COPY?
					; NO FREE CRLF, OR IT WILL BE ECHOED
	JRST	FILLM1		;NO LOCAL COPY
	PUSHJ	P,SETFLC	;GET FILL CLASS
	MOVE	T2,FLLCRP(T2)	;NEED A FREE LINEFEED.GET CRLF
	IBP	T2		;AND COUNT IT PAST CR
	JRST	FLLPOP		;AND GO STORE RESULT

FILLM1:	PUSHJ	P,SETFLC	;GET FILLER CLASS
	MOVE	T2,FLLCOP(T2)	;GET FILLERS FOR CR OUTPUT
	JRST	FLLPOP		;GO STORE AND RETURN

RETYPE::
IFN FTNET,<			;IF WE HAVE THE NETWORK, WE
	SKIPGE	LDBREM(U)	; BETTER MAKE SURE THAT THIS ISN'T A VTM
	POPJ	P,		; CAUSE IF IT IS, THE CHUNKS ARE ALL
>				; MESSED UP AND WE WILL "RCC"
	SCNOFF
	SKIPN	T1,LDBBKU(U)	;SKIP IF BREAK IN BUFFER
	MOVE	T1,LDBTIT(U)	;ELSE GET START OF BUFFER
	PUSHJ	P,CTISBP	;STORE THE BYTE POINTER
	HRRZM	U,.CPCML##	;REMEMBER LINE # FOR DEBUGGING
	SCNON
RETYPL:	PUSHJ	P,CCTYI		;GET A BYTE.
				;YOU MAY THINK WE SHOULD CALL COMTYI, YOU
				; ARE WRONG.
	CAIN	T3,12		;DONE?
	JRST	[SETZM .CPCML##	;YES
		 POPJ P,0]	;RETURN
	PUSHJ	P,USEARO	;TYPE OUT CHAR, IN ARROW MODE
	JRST	RETYPL		;LOOP FOR MORE

STOPCM:	PUSH	P,T1		;SAVE T1
	MOVEI	T1,0		;GET A ZERO AND USE IT TO
	SCNOFF			;INTERLOCK W.R.T. CCTYI
	PUSHJ	P,CTISBP	;  SAY THERE IS NO COMMAND ON THIS LINE
	SCNON			;RETURN INTERLOCK
	JRST	TPOPJ##		;RESTORE T1 AND RETURN
;DATA SENT OUT AS FILLERS

FILLER:	BYTE	(9) 377,377,377,377	;BLOCK OF 23 RUBOUTS
	BYTE	(9) 377,377,377,377
FILLRX:	BYTE	(9) 377,377,377,377
	BYTE	(9) 377,377,377,377
FILLRY:	BYTE	(9) 377,377,377,377
FILLRZ:	BYTE	(9) 377,377,377,0	;ZERO TERMINATES THE STRING

KSPACE:	BYTE	(9) 240,240,240,240	;BLOCK OF 7 SPACES.
	BYTE	(9) 240,240,240,0

KLINEF:	BYTE	(9) 12,12,12,12	;BLOCK OF 7 LINEFEEDS
	BYTE	(9) 12,12,12,0

FILLIP:	POINT	9,KSPACE	;POINTERS FOR TAB SIMULATION
	POINT	9,KSPACE,8
	POINT	9,KSPACE,17
	POINT	9,KSPACE,26
	POINT	9,KSPACE,35
	POINT	9,KSPACE+1,8
	POINT	9,KSPACE+1,17
	0

FLSLD0:	BYTE	(9) 12,12,12,12	;LINEFEEDS W/O FILLERS.
FLSKD0:	BYTE	(9) 12,12,12,0	; ..

FLSLD1:	BYTE	(9) 377,377,12,377	;LINEFEEDS WITH 2 FILLERS.
	BYTE	(9) 377,12,377,377
	BYTE	(9) 12,377,377,12
FLSKD1:	BYTE	(9) 377,377,12,377
	BYTE	(9) 377,12,377,377
	BYTE	(9) 12,377,377,0
FLBPXF:	BYTE	(9) 223,0,0,0
FLLKSP:	POINT	9,FLSKD0	;POINTERS TO SIMULATE ↑K
	POINT	9,FLSKD0
	POINT	9,FLSKD1
	POINT	9,FLSKD1

FLLLSP:	POINT	9,FLSLD0	;POINTERS TO SIMULATE ↑L
	POINT	9,FLSLD0
	POINT	9,FLSLD1
	POINT	9,FLSLD1

FLBLXF:	BYTE	(9) 207,223,377,0	;DATA - BELL,XOFF,RUBOUT
FLPBEL::POINT	9,FLBLXF	;POINTER TO BELL-XOFF-RUBOUT
FLPXOF:	POINT	9,FLBLXF,8	;POINTER TO XOFF AND RUBOUT
FLPPXF::POINT	9,FLBPXF	;POINTER TO XOFF WITH NO FILL
FLLXON:	BYTE	(9) 21,377,0	;DATA - XON,RUBOUT
FLPXON:	POINT	9,FLLXON	;POINTER TO XON-RUBOUT
	SUBTTL	TIMING ROUTINE

;SUBROUTINE CALLED EVERY SECOND AT CLOCK LEVEL.
;CHECKS FOR IRMA. TIMES IMAGE INPUT. RUNS MODEMS.

SCNSEC::MOVEI	J,TCONLN##	;PREPARE TO SEARCH LINE TABLE
	PUSHJ	P,SAVE2##
IFN FTMP,<MOVE P2,.CPCPN##>	;CPU #
	SETZM	%SCNAL
SCNSIL:	MOVE	U,LINTAB##(J)	;GET ADR OF LDB
	MOVE	T1,LDBDCH(U)	;GET THE CHARACTERISTICS
IFN FTMP,<			;IF SMP, CHECK WHICH CPU WE'RE ON
	LDB	T2,LDPCPU	;GET # OF LINE'S OWNER
	TRNE	T1,LDRREM	;BUT IF IT'S A NETWORK LINE, ONLY DO
	MOVE	T2,BOOTCP##	;  TIMING ON THE BOOT CPU
	CAIE	T2,(P2)		;ARE WE ON RIGHT CPU
	JRST	SCNSIS		;IF WRONG CPU, SKIP THIS LINE
>
	TLNE	T1,LDLIMI	;IMAGE INPUT STATE?
	PUSHJ	P,SCSIMG	;YES. GO TIME IT
	MOVE	T1,LDBDCH(U)	;SCSIMG CAN CLOBBER THIS
	JUMPL	T1,SCNSIN	;IF IDLE?
	AOS	%SCNAL
IFN FTCIMP,<			;[arpa]
	TRNE	T1,LDRSHC!LDR2741!LDRPTY!LDRIMP ;[arpa] YES - HUNG CHECKING?
>				;[arpa]
IFE FTCIMP,<			;[arpa]
	TRNE	T1,LDRSHC!LDR2741 ;YES - HUNG CHECKING?
>				;[arpa]
	JRST	SCNSIN		;NO
IFN FTHDPX,<
	MOVE	T1,LDBBY2(U)	;GET HALF DUPLEX FLAGS
	TLNE	T1,L2LHD3+L2LHD4	;DURING ECHO FAILURE?
	JRST	SCNSIN		;YES. DON'T DO HUNG CHECK
>
	MOVSI	T1,LPLIRM	;SET UP SYNC BIT
	TDNE	T1,LDBPAG(U)	;ON FROM 1 SECOND AGO?
	JRST	[PUSHJ P,TOREQ	;REQUEUE SO OUTPUT STARTS
		 MOVSI	P1,L1LOFL
		 MOVEI	T1,ISROFL
		 PUSHJ	P,@LDBISR(U)
		   IORM	P1,LDBOFL(U)
		 JRST   SCNSIN]	;LOOK AT NEXT LINE
	IORM	T1,LDBPAG(U)	;TURN ON SYNC BIT FOR THIS SECOND
SCNSIN:	MOVE	T1,LDBTIC(U)
	ADD	T1,LDBECC(U)
	SKIPE	T1
	AOS	%SCNAL
	SKIPL	LDBOFL(U)
	JRST	SCNSIS
	MOVSI	P1,L1LOFL
	MOVEI	T1,ISROFL
	PUSHJ	P,@LDBISR(U)
	  SKIPA
	ANDCAM	P1,LDBOFL(U)
SCNSIS:	SOJGE	J,SCNSIL
IFN FTMP,<
	SKPCPU	(0)		;ONLY ON MASTER
	PJRST	@.CPISR##
>
	SOSGE	SNDCTR##
	SETZM	SNDCTR##
	AOS	T2,%SCNAL
	CAIGE	T2,20
	MOVEI	T2,20
	MOVE	T1,TTFREN##
	IMULI	T1,↑D12
	IDIV	T1,T2
	CAIGE	T1,↑D80
	MOVEI	T1,↑D80
	EXCH	T1,TIWRNN	;STORE NEW LIMIT AND GET PREVIOUS
	MOVEM	T1,TIWRN1	;STORE PREVIOUS
	MOVE	T1,TIWRNN	;GET NEW BACK
	CAIGE	T1,↑D600	;IF IT ISN'T AT LEAST 600
	MOVEI	T1,↑D600	; THEN MAKE IT 600
	MOVEM	T1,RPIMWN	;AND SAVE
IFE FTMODM,<PJRST @.CPISR##>	;CALL EACH ISR
				;ELSE FALL THRU INTO DATASET ROUTINE
IFN FTMODM,<

;ROUTINE TO DO ONCE-A-SECOND TIMING OF MODEMS. TIMES OUT INTERVALS
;FROM RING TO CARRIER ON, FROM CARRIER ON TO LEGAL COMMAND,
; AND FROM CARRIER OFF TO HANG UP.

DSCSEC:	SKIPL	J,DSCPTR##	;GET DATASET CONTROL POINTER
	JRST	DSCSC1		;THERE ARE NONE IN THIS CONFIGURATION
	HLLZS	J		;CLEAR RIGHT HALF FOR INDEXING
DSCSLP:	MOVE	T1,DSCTAB##(J)	;GET TABLE ENTRY
	TLNE	T1,DSCBLI	;BLIND STILL ON?
	JRST	DSCSC3		;YES.
	SCNOFF			;CAN'T ALLOW INTERRUPTS HERE
	LDB	T3,DSTIMP	;GET THE TIME SINCE RING OR CARRIER FAILURE
	SOSL	T3		;COUNT IT DOWN. WAS IT 0?
	DPB	T3,DSTIMP	;NO. STORE NEW VALUE
	JUMPN	T3,[SCNON	;UNLESS NEWLY 0, ALLOW INTERRUPTS
		    JRST DSCSNY]; AND GO TO NEXT
	MOVSI	T3,DSCFAI+DSCSWC;CLEAR FAIL AND SOFTWARE BITS
	ANDCAB	T3,DSCTAB##(J)	; IN CORE
	SCNON			;OK FOR INTERRUPTS NOW.
IFN FTDIAL,<
	TLNE	T3,DSCDLW	;IN DIALLER WAIT?
	JRST	DSCSDF		;YES. DIALLER HAS FAILED.
>
	HRRZ	U,LINTAB##(T1)	;GET THE LDB ADDRESS
				; OF THE RELATED TERMINAL LINE
IFN FTNET,<
	MOVE	T1,LDBREM(U)	;GET THE REMOTE STATUS BITS,
	TLNE	T1,LRLVTM	;  AND IF THIS IS A VTM LINE
	PUSHJ	P,VTMDSF##	;  SIGNAL CARRIER OFF TO THE REMOTE
>
	PUSHJ	P,LDBCLR	;CLEAR OUT LDB STATUS
	HRRZ	F,LDBDDB(U)	;SEE IF THERE'S A JOB.
	JUMPE	F,DSCSC2	;SKIP THIS IF NO JOB
	MOVE	T1,DEVMOD(F)	;MAY BE A JOB. GET MODE WORD.
	TLNN	T1,TTYATC	;CONTROLLING A JOB.
	JRST	DSCSC2		;NOT A CONTROLLING TERMINAL. NO COMMAND

	PUSHJ	P,DSCDET	;DETACH THE GUY (.BYE)
DSCSC2:	MOVEI	T3,DSTOFF	;SOFTWARE CODE TO TURN OFF DATASET
	MOVEI	U,0(J)		;TABLE ADDRESS AS LINE NUMBER
	PUSHJ	P,DSCCAL	;SEND TO APPROPRIATE HARDWARE DEVICE
DSCSNY:	AOBJN	J,DSCSLP	;COUNT THROUGH ALL LINES
DSCSC1:	PJRST	@.CPISR##	;DO ISR TIMING
;STILL IN FTMODM
DSCSC3:	MOVSI	T3,DSCBLI	;SET FOR BLIND BIT
	TLNE	T1,DSCNCR	;NEW CARRIER BIT STILL ON?
	MOVSI	T3,DSCNCR	;YES. CLEAR IT INSTEAD
	ANDCAM	T3,DSCTAB##(J)	;CLEAR BIT IN TABLE
	JRST	DSCSNY		;AND GO ON TO NEXT MODEM

IFN FTDIAL,<
DSCSDF:	SETOM	TTYDDL##	;CLEAR DIALLER CODE INTERLOCK
	MOVEI	U,0(J)		;COPY TABLE INDEX
	PUSHJ	P,DSROF1	;CLEAR OUT THE HARDWARE FOR THIS LINE.
	MOVSI	T1,DSCDLF	;FLAG THAT DIALLING LOST
	IORB	T1,DSCTAB##(J)	; ..
	PUSHJ	P,DSCWAK	;WAKE THE SLEEPING JOB, IF ANY
	JRST	DSCSNY		;LOOK FURTHER THRU DSCTAB

DSCWAK:	MOVE	T1,LINTAB##(T1)	;GET THE LDB ADDRESS FOR THIS DATASET'S TERMINAL
	HRRZ	F,LDBDDB(T1)	;GET THE DDB, IF ANY
	SKIPE	T1		;ANY?
	LDB	T1,PJOBN##	;YES. GET JOB NUMBER
	JUMPE	T1,CPOPJ##	;ANY?
	PJRST	WAKJOB##	;YES. WAKE IT.
> ;END OF FTDIAL

DSTIMP:	POINT	6,DSCTAB##(J),17	;POINTERS TO TIME BYTE
DSTMPL:	POINT	6,DSCTAB##(U),17	;SAME BUT DIFFERENT AC INDEX
				;MUST AGREE WITH DSCTMM
> ;END OF FTMODM
;SUBROUTINE TO TIME THE IMAGE MODE INPUT STATE, SET END OF FILE IF
;IT TIMES OUT, AND FORCE CONTROL C UNLESS SLAVED ON SECOND TIME-OUT


SCSIMG:	PUSH	P,J		;SAVE COUNTER. WILL BE CLOBBERED.
	LDB	T3,LDPTIM	;GET THE IMAGE TIME BYTE
	SOSL	T3		;COUNT IT DOWN. TOO LOW?
	DPB	T3,LDPTIM	;NO STORE NEW VALUE.
	JUMPG	T3,IPOPJ##	;IF NO TIMEOUT YET, GO BACK TO LOOP
	HRRZ	F,LDBDDB(U)	;GET LINE'S JOB DATA BLOCK
	JUMPE	F,SCSIM2	;NO JOB? TIME AGAIN
IFN FTCIMP,<			;[arpa]
	MOVEI	T1,INDSTM##	;[arpa] HAS USER DISABLED IMAGE MODE TIMEOUT?
	TDNE	T1,DEVIOS(F)	;[arpa] ...
	  JRST	IPOPJ##		;[arpa] yes.  don't check.
>				;[arpa]
	MOVSI	S,FRCEND	;CAUSE UUO ROUTINE TO FORCE END
	TDNE	S,DEVIOS(F)	;ON YET?
	JRST	SCSIM1		;ON ALREADY. PANIC.
	IORB	S,DEVIOS(F)	;NO. SET IT NOW AND TIME OUT AGAIN
SCSIM2:	MOVEI	T3,IMGTIM	;SET TIME TO NEXT PANIC
	DPB	T3,LDPTIM	;STORE IN TIME BYTE
	PUSHJ	P,RCVWAK	;AND WAKE UP JOB
	JRST	IPOPJ##		;GO RESTORE J AND RETURN

SCSIM1:	MOVSI	S,TTYATC	;GET A BIT
	TDNE	S,DEVMOD(F)	;IS THIS AN I/O DEVICE?
	TLNE	T1,LDLSLV	;IS THIS A SLAVE TERMINAL?
	JRST	SCSIM2		;YES. CAN'T DO CONTROL C
	PUSHJ	P,CNCMOD	;NO. SET TO COMMAND LEVEL
	MOVSI	T1,LDBCMF	;FORCE COMMAND
	DPB	T1,LDPCMX	;CONTROL C INDEX
	IORM	T1,LDBDDB(U)	;AND FLAG COMMAND DECODER
	PUSHJ	P,COMSET	;WAKE UP COMMAND ROUTINE,
	JRST	IPOPJ##		;RESTORE AC AND RETURN
;OUTPUT SERVICE ROUTINE FOR CTY

IFN FTKI10!FTKS10,<
CTYSTO::MOVEI	T1,.CPCTQ##	;POINT TO CTY OUTPUT QUEUE HEADER
	PUSHJ	P,TOTAKE	;GET A LINE NUMBER (CHECK QUEUE)
	  POPJ	P,		;NONE WAITING
	SKIPGE	LDBDCH(U)
	PUSHJ	P,XMTCHR	;GET NEXT OUTPUT CHARACTER
	  POPJ	P,		;LINE IS NOW IDLE
	PUSHJ	P,CLRIRM	;CLEAR IRMA BH
CTYTYO:	ANDI	T3,377		;REMOVE JUNK
IFN FTKI10,<
	DATAO	CTY,T3		;SEND THE CHARACTER
>
IFN FTKS10,<
	HRRZ	T1,LINTAB##+KLILIN##
	CAIN	T1,(U)		;KLINIK LINE?
	JRST	KLITYO		;YES--GO TO IT
	IORI	T3,CTYOVL	;SET VALID FLAG
	MOVEM	T3,CTYOWD	;PUT IN OUTPUT WORD
CTYTY1:	RDAPR	T1		;GET CPU PI LEVEL
	ANDI	T1,SP.PIA	; AND ONLY THE PI LEVEL
	WRAPR	SP.SSF+SP.IFE(T1) ;INTERRUPT THE 8080
>
IFN FTHDPX!FTTRACK,<
	DPB	T3,LDPECK	;FOR LIGHTS ONLY (CTY IS FDX)
>
	POPJ	P,0		;AND RETURN
IFN FTKS10,<
KLITYO:	IORI	T3,KLIOVL	;SET VALID BIT
	MOVEM	T3,KLIOWD	;PUT CHAR IN OUTPUT WORD
	JRST	CTYTY1		;GO INTERRUPT 8080
>;END IFN FTKS10
>;END IFN FTKI10!FTKS10
;ROUTINE TO ADJUST HORIZONTAL POSITION COUNT FOR CHARACTER TO
;OUTPUT FROM BUFFER. CALL WITH T3, U SET UP.

ADJHP:	PUSH	P,T3		;SAVE CHARACTER
	ANDI	T3,177		;JUST CHARACTER BITS
	CAIL	T3,177		;RUBOUT
	JRST	T3POPJ##	;DOESN'T SPACE
	CAIL	T3,40		;NON-IMAGE CONTROL CHARACTER?
	JRST	ADJHP1		;NO, SIZE IS ONE
	PUSH	P,T2
	CAIN	T3,11		;IS THIS A TAB?
	JRST	ADJHP2		;YES, GO FIGURE OUT HOW BIG IT IS
	CAIN	T3,15		;CARRIAGE RETURN?
	JRST	ADJHP3		;SETS HPOS BACK TO START
	CAIE	T3,10		;BACKSPACE?
	JRST	T23PPJ		;NO, OTHER DON'T CHANGE HPOS
	PUSHJ	P,HPOS		;GET CURRENT POSITION
	JUMPE	T2,T23PPJ	;IF AT START OF LINE
	SOS	LDBHPS(U)	;ELSE DECREMENT POSITION BY ONE
	JRST	T23PPJ		;AND RETURN

;HERE FOR CARRIAGE RETURN

ADJHP3:	PUSHJ	P,SCNBOL	;BACK TO START OF LINE
	JRST	T23PPJ		;AND RETURN

;HERE FOR TAB

ADJHP2:	PUSHJ	P,HPOS		;CURRENT HORIZONTAL POSITION
	DPB	T2,POHPOS	;SAVE LOW 3 BITS FOR SIMULATION
	ANDI	T2,7		;ISOLATE (POSITION MOD 8)
	MOVN	T2,T2		; -(POSITION MOD 8)
	ADDI	T2,10		; 8-(POSITION MOD 8)
	ADDM	T2,LDBHPS(U)	;FIX HPOS COUNTER
	JRST	T23PPJ		;AND RETURN

;HERE FOR PRINTING CHARACTER

ADJHP1:	AOSA	LDBHPS(U)	;INCREMENT POSITION
T23PPJ:	POP	P,T2
	JRST	T3POPJ##
;HPOS -- SUBROUTINE TO FETCH THE CURRENT HORIZONTAL POSITION ON A LINE
;CALL
;	PUSHJ	P,HPOS
;	<ALWAYS RETURN HERE>
;EXIT WITH T2 = HORIZONTAL POSITION.  PRESERVES ALL OTHERS AC'S.

HPOS::	LDB	T2,LDPWID	;GET CARRIAGE WIDTH
	ADD	T2,LDBHPS(U)	;COMPUTE HORIZONTAL POSITION
	POPJ	P,		;AND RETURN IT


;ROUTINE TO SET A LINE BACK TO THE BEGINNING

SCNBOL:	PUSH	P,T2		;SAVE ALL AC'S
	LDB	T2,LDPWID	;GET WIDTH
	MOVNM	T2,LDBHPS(U)	;INITIAL VALUE OF HORIZONTAL POS COUNTER
	MOVEI	T2,0
	DPB	T2,POHPOS	;INITIAL LOW ORDER 3 BIT COUNTER
	JRST	T2POPJ##	;RESTORE T2 AND RETURN
;ROUTINE TO SUPPRESS BLANK LINES
IFN FTTBLK,<

BLSUPI:	PUSHJ	P,HPOS		;GET HORIZONTAL POSITION
	HRLI	T2,LPLSLF	;  (LPLSLF BIT IN LH)
	TRZE	T2,-1		;ANYTHING ON THIS LINE?
	ANDCAM	T2,LDBPAG(U)	;YES - CLEAR BIT TO ALLOW L.F.
	PUSH	P,T3		;SAVE CHARACTER
	ANDI	T3,177		;REDUCE TO 7-BIT ASCII
	CAIL	T3,12		;IS CHARACTER LF, VT, OR FF?
	CAILE	T3,14		; . . .
	JRST	T3POPJ##	;NO
	IORM	T2,LDBPAG(U)	;SET BIT TO SUPPRESS LF'S
	JRST	T3POPJ##	;BUT ALWAYS ECHO INPUT <CR><LF>S

BLSUPO:	PUSHJ	P,HPOS		;GET HORIZONTAL POSITION
	HRLI	T2,LPLSLF	;  (LPLSLF BIT IN LH)
	TRZE	T2,-1		;ANYTHING ON THIS LINE?
	ANDCAM	T2,LDBPAG(U)	;YES - CLEAR BIT TO ALLOW L.F.
	PUSH	P,T3		;SAVE CHARACTER
	ANDI	T3,177		;REDUCE TO 7-BIT ASCII
	CAIL	T3,12		;IS CHARACTER LF, VT, OR FF?
	CAILE	T3,14		; . . .
	JRST	T3POPJ##	;NO
	CAIN	T3,12		;YES-SUPPRESS LF?
	TDNN	T2,LDBPAG(U)
	SKIPA	T3,[12]		;NO-TURN VT OR FF INTO LF
	MOVEI	T3,0		;YES-TURN LF INTO NULL
	IORM	T2,LDBPAG(U)	;SET BIT TO SUPPRESS LF'S
	MOVE	T1,CHTABL(T3)	;GET BITS FOR NEW CHARACTER
	POP	P,T2		;RESTORE OLD CHARACTER
	TRNE	T2,200		;PARITY/VTM ECHO BIT?
	TRO	T3,200		;YES, ADD IT
	POPJ	P,
> ;IFN FTTBLK
;SUBROUTINE TO WAKE UP JOB IF IT IS IN TERMINAL INPUT WAIT. CALL WITH
;LINE SET UP. IT WILL SET DDB AND S AS NEEDED.

RCVWAK:
IFN FTCIMP,<			;[arpa]
	SKIPE	F,LDBIMP(U)	;[arpa] CROSSPATCHED TO IMP?
	  PJRST	TTIMPI		;[arpa] YES, HANDLE DIFFERENTLY
>				;[arpa]
	HRRZ	F,LDBDDB(U)	;GET ADDRESS OF ATTACHED DDB
	JUMPE	F,CPOPJ##	;IF NONE,SKIP THIS CODE
	PUSH	P,T1		;SAVE T1
	LDB	T1,PJOBN##	;GET JOB NUMBER OF TERMINAL OWNER
	MOVSI	S,TTILCE##	;IS JOB ENABLED FOR WAKE UP
	TDNE	S,JBTRTD##(T1)	;DURING A HIBERNATE
	JRST	WAKJB		;YES, GO WAKE JOB
WAKJBR:	POP	P,T1		;RESTORE T1

	MOVE	S,DEVIOS(F)	;GET STATUS OF TERMINAL FROM DDB
IFN FTPI,<TLZ S,IO>		;MAKE SURE BIT IS RIGHT
	TLNE	S,IOW		;JOB IN I/O WAIT FOR TERMINAL?
	TLNE	S,TTYOUW	;YES. FOR INPUT WAIT?
IFN FTPI,<JRST PSIIOD##>	;GENERATE PSI SO USER WILL KNOW I/O IS DONE
IFE FTPI,<POPJ P,0>		;NO--DON'T WAKE JOB.

TTWAKE::PUSH	P,T1		;SAVE VOLATILE AC'S
	PUSH	P,T2		; ..
	LDB	T1,PJOBN##	;IS JOB # IN DDB ZERO?
	JUMPE	T1,TTWAKX	;EXIT IF ZERO
	MOVE	S,DEVIOS(F)	;MAKE SURE S IS CORRECT
IFN FTPSCD,<
	MOVE	T1,LDBDCH(U)	;LINE CHARACTERISTICS
	JUMPL	S,TTWAKO	;OUTPUT?
TTWAKI:	TRNE	T1,LDRPTY	;INPUT. PTY?
	AOSA	%PISJB##	;YES
	  AOS	%TISJB##	;NO
	JRST	TTWAKB
TTWAKO:	TRNE	T1,LDRPTY	;OUTPUT. PTY?
	AOSA	%POSJB##	;YES
	  AOS	%TOSJB##	;NO
TTWAKB:>
	MOVEI	S,IOACT		;CLEAR I/O ACTIVE
	ANDCAB	S,DEVIOS(F)	;IN DDB FOR THIS JOB
	PUSHJ	P,STTIOD##	;CALL STTIOD FOR TERMINALS, PTYS
TTWAKX:	POP	P,T2		;RESTORE AC'S
	PJRST	TPOPJ##		;RETURN FROM RCVWAK

;ROUTINE TO SEE IF CHARACTER SPECIAL HANDLING SHOULD BE SUPPRESSED
;PRESERVES T1

FULLCQ:	PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  TLNN	U,LDLBKA+LDLFCS	;NO. DOES USER WANT ALL CHARACTERS?
	AOS	(P)		;NO. COMMAND OR NOT SMART USER
	POPJ	P,0		;SMART USER. NON-SKIP RETURN.
WAKJB:	PUSH	P,T2		;SAVE AC'S
	PUSH	P,T3
	MOVSI	T2,(JS.HIB)	;IS JOB SLEEPING
	TDNE	T2,JBTST2##(T1)	;OR HIBERNATING?
	PUSHJ	P,WAKJOB##	;HIBERNATING: WAKE THE JOB
	POP	P,T3		;RESTORE THE AC'S
	POP	P,T2
	JRST	WAKJBR		;RETURN TO NORMAL PROGRAM FLOW

;THE FOLLOWING ROUTINE IS CALLED BY THE HIBERNATE UUO TO
;PUT THE TERMINAL INTO CHARACTER MODE.  T1 IS PRESERVED.

HIBTTY::PUSH	P,T1		;SAVE T1
	PUSHJ	P,TTYFND	;FIND THIS JOB'S TTY
	JUMPE	U,TPOPJ##	;NO TERMINAL FOR THIS JOB
	MOVSI	T1,TTIACE##	;HIBERNATE IN CHARACTER MODE?
	TDNN	T1,JBTRTD##(J)
	JRST	HIBTTL		;NO, IT MUST BE LINE MODE
	PUSHJ	P,TTCCHK	;CHECK IF A CHARACTER IS ALREADY PRESENT
	  JRST	TPOPJ##		;NO LINE, ECHO STARTED
HIBSET:	MOVSI	T1,WAKEB##	;LINE OR CHARACTER PRESENT
	IORM	T1,JBTRTD##(J)	;DON'T HIBERNATE
	PJRST	TPOPJ##		;RESTORE T1 AND RETURN (TO UUOCON)
HIBTTL:	PUSHJ	P,TTLCHK	;CHECK FOR A LINE PRESENT
	  JRST	TPOPJ##		;NO LINE, ECHO STARTED
	JRST	HIBSET		;YES, DON'T GO TO SLEEP

;TABLE OF CONTROL CHARACTERS - LH=BITS, RH=DISP ADDR ON RCV INT

;DEFINITION OF BITS IN THIS TABLE
CHBRK==:1	;THIS IS A BREAK CHARACTER
CHUAE==:2	;THIS CHARACTER ECHOES AS ↑X
CHFIL==4	;THIS CHARACTER REQUIRES FILLERS AT SOME SPEEDS
CHALT==10	;THIS CHARACTER IS ONE OF THE THREE ALTMODES.
CHRIA==20	;THIS CHARACTER REQUIRES RCV INT LEVEL ACTION
CHCRET==40	;THIS IS A CARRIAGE RETURN (NEEDED FOR SETFLO)
CHCNC==100	;THIS IS CONTROL C
CHDEL==200	;THIS IS DELETE
CHFILO==400	;BIT ADDED FOR OUTPUT FILLER ROUTINE (NOT IN TABLE)
CHCRE==1000	;THIS CHARACTER GETS CRLF AFTER ITS ↑ X ECHO
CHVPOS==2000	;VERT. POSITIONING SIMULATED WITH FORM FEEDS
CHEPAR==:4000	;THIS BIT SET IF CHARACTER IS EVEN PARITY
CHDELW==10000	;THIS IS A CONTROL W
CHPUNC==20000	;THIS IS A PUNCTUATION CHARACTER
IFN FTCIMP,<	;[arpa]
CHXPIH==40000	;[arpa] SPECIAL HANDLING EVEN IF CROSSPATCHED TO IMP
CHSUSP==100000	;[arpa] SUPPRESS ECHO IF SPECIAL ACTION SUPPRESSED
>		;[arpa]
IFE FTCIMP,<	;[arpa]
CHXPIH==0	;DEFINED, BUT HAVE NO EFFECT
CHSUSP==0	;DITTO
>		;[arpa]
CHSPO==400000	;REQUIRES SPECIAL CHECKING ON OUTPUT.  MUST BE THE
		;SIGN BIT.

CHTABL:	XWD	CHSPO+CHRIA+CHEPAR+CHPUNC,RINUL			;↑@ NUL 000
IFN FTMIC,<
	XWD	CHSPO+CHRIA+CHUAE+CHPUNC,RICA			;↑A SOH 001
	XWD	CHSPO+CHRIA+CHUAE+CHPUNC,RICB			;↑B STX 002
>
IFE FTMIC,<
	XWD	CHSPO+CHUAE+CHPUNC,0				;↑A SOH 001
	XWD	CHSPO+CHUAE+CHPUNC,0				;↑B STX 002
>
	XWD	CHSPO+CHUAE+CHBRK+CHRIA+CHCRE+CHCNC+CHEPAR+CHPUNC,RICC	;↑C ETX 003
	XWD	CHSPO+CHUAE!CHRIA+CHPUNC,RICD			;↑D EOT 004
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;↑E ENQ 005
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;↑F ACK 006
	XWD	CHSPO+CHBRK+CHPUNC,0				;↑G BEL 007
;[arpa]	XWD	CHSPO+CHBRK+CHRIA+CHPUNC,RIBSP			;↑H BS 010
	XWD	CHSUSP+CHSPO+CHBRK+CHRIA+CHPUNC,RIBSP		;[arpa]↑H BS 010
	XWD	CHSPO+CHFIL+CHEPAR,0				;↑I HT  011
	XWD	CHSPO+CHFIL+CHBRK+CHEPAR+CHPUNC,0		;↑J LF  012
	XWD	CHSPO+CHFIL+CHBRK+CHVPOS+CHPUNC,0		;↑K VT  013
	XWD	CHSPO+CHFIL+CHBRK+CHVPOS+CHEPAR+CHPUNC,0	;↑L FF  014
;[arpa]	XWD	CHSPO+CHRIA+CHFIL+CHCRET+CHPUNC,RICM		;↑M CR  015
	XWD	chxpih+CHSPO+CHRIA+CHFIL+CHCRET+CHPUNC,RICM	;[arpa]↑M CR  015
	XWD	CHSPO+CHUAE+CHPUNC,0				;↑N SO  016
	XWD	CHSPO+CHUAE+CHRIA+CHCRE+CHEPAR+CHPUNC,RICO	;↑O SI  017
IFN FTMIC,<
	XWD	CHSPO+CHRIA+CHUAE+CHPUNC,RICP			;↑P DLE 020
>
IFE FTMIC,<
	XWD	CHSPO+CHUAE+CHPUNC,0				;↑P DLE 020
>
	XWD	CHSPO+CHUAE+CHFIL+CHRIA+CHEPAR+CHPUNC,RICQ	;↑Q XON 021
	XWD	CHSPO+CHUAE+CHFIL+CHRIA+CHBRK+CHEPAR+CHPUNC,RICR;↑R TAPE 022
	XWD	CHSPO+CHUAE+CHRIA+CHFIL+CHPUNC,RICS		;↑S XOFF 023
	XWD	CHSPO+CHUAE+CHFIL+CHRIA+CHBRK+CHEPAR+CHPUNC,RICT;↑T- NTAPE 024
;[arpa]	XWD	CHSPO+CHUAE+CHRIA+CHCRE+CHBRK+CHPUNC,RICU	;↑U NAK 025
	XWD	CHSUSP+CHSPO+CHUAE+CHRIA+CHCRE+CHBRK+CHPUNC,RICU ;[arpa]↑U NAK 025
	XWD	CHSPO+CHUAE+CHPUNC,0				;↑V SYN 026
;[arpa]	XWD	CHSPO+CHUAE+CHRIA+CHEPAR+CHPUNC+CHDEL+CHDELW+CHBRK,RIDEL ;↑W ETB 027
	XWD	CHSUSP+CHSPO+CHUAE+CHRIA+CHEPAR+CHPUNC+CHDEL+CHDELW+CHBRK,RIDEL ;[arpa]↑W ETB 027
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;↑X CAN 030
	XWD	CHSPO+CHUAE+CHPUNC,0				;↑Y EM  031
	XWD	CHSPO+CHUAE+CHBRK+CHCRE+CHPUNC,0		;↑Z SUB 032
;[arpa]	XWD	CHSPO+CHBRK+CHALT+CHRIA+CHEPAR+CHPUNC,RIALT	;↑[ ESC 033
	XWD	CHSUSP+CHSPO+CHBRK+CHALT+CHRIA+CHEPAR+CHPUNC,RIALT ;[arpa]↑[ ESC 033
	XWD	CHSPO+CHUAE+CHPUNC,0				;↑\ FS  034
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;↑] GS  035
	XWD	CHSPO+CHUAE+CHEPAR+CHPUNC,0			;↑↑ RS  036
	XWD	CHSPO+CHUAE+CHPUNC,0				;↑← US  037

		0						;SPACE	040
	XWD	CHEPAR+CHPUNC,0					;!	041
	XWD	CHEPAR+CHPUNC,0					;"	042
	XWD	CHPUNC,0					;#	043
	XWD	CHEPAR+CHPUNC,0					;$	044
	XWD	CHPUNC,0					;%	045
	XWD	CHPUNC,0					;&	046
	XWD	CHEPAR+CHPUNC,0					;'	047
	XWD	CHEPAR+CHPUNC,0					;(	050
	XWD	CHPUNC,0					;)	051
	XWD	CHPUNC,0					;*	052
	XWD	CHEPAR+CHPUNC,0					;+	053
	XWD	CHPUNC,0					;,	054
	XWD	CHEPAR+CHPUNC,0					;-	055
	XWD	CHEPAR+CHPUNC,0					;.	056
	XWD	CHPUNC,0					;/	057
	XWD	CHEPAR,0					;0	060
		0						;1	061
		0						;2	062
	XWD	CHEPAR,0					;3	063
		0						;4	064
	XWD	CHEPAR,0					;5	065
	XWD	CHEPAR,0					;6	066
		0						;7	067
		0						;8	070
	XWD	CHEPAR,0					;9	071
	XWD	CHEPAR+CHPUNC,0					;:	072
	XWD	CHPUNC,0					;;	073
	XWD	CHEPAR+CHPUNC,0					;<	074
	XWD	CHPUNC,0					;=	075
	XWD	CHPUNC,0					;>	076
	XWD	CHEPAR+CHPUNC,0					;?	077
	XWD	CHPUNC,0					;@	100
	XWD	CHEPAR,0					;A	101
	XWD	CHEPAR,0					;B	102
		0						;C	103
	XWD	CHEPAR,0					;D	104
		0						;E	105
		0						;F	106
	XWD	CHEPAR,0					;G	107
	XWD	CHEPAR,0					;H	110
		0						;I	111
		0						;J	112
	XWD	CHEPAR,0					;K	113
		0						;L	114
	XWD	CHEPAR,0					;M	115
	XWD	CHEPAR,0					;N	116
		0						;O	117
	XWD	CHEPAR,0					;P	120
		0						;Q	121
		0						;R	122
	XWD	CHEPAR,0					;S	123
		0						;T	124
	XWD	CHEPAR,0					;U	125
	XWD	CHEPAR,0					;V	126
		0						;W	127
		0						;X	130
	XWD	CHEPAR,0					;Y	131
	XWD	CHEPAR,0					;Z	132
	XWD	CHPUNC,0					;[	133
	XWD	CHEPAR+CHPUNC,0					;/	134
	XWD	CHPUNC,0					;]	135
	XWD	CHPUNC,0					;↑	136
	XWD	CHEPAR+CHPUNC,0					;←	137

;THESE LETTERS ARE LOWER-CASE
	XWD	CHEPAR+CHPUNC,0					;`	140
		0						;a	141
		0						;b	142
	XWD	CHEPAR,0					;c	143
		0						;d	144
	XWD	CHEPAR,0					;e	145
	XWD	CHEPAR,0					;f	146
		0						;g	147
		0						;h	150
	XWD	CHEPAR,0					;i	151
	XWD	CHEPAR,0					;j	152
		0						;k	153
	XWD	CHEPAR,0					;l	154
		0						;m	155
		0						;n	156
	XWD	CHEPAR,0					;o	157
		0						;p	160
	XWD	CHEPAR,0					;q	161
	XWD	CHEPAR,0					;r	162
		0						;s	163
	XWD	CHEPAR,0					;t	164
		0						;u	165
		0						;v	166
	XWD	CHEPAR,0					;w	167
	XWD	CHEPAR,0					;x	170
		0						;y	171
		0						;z	172
	XWD	CHEPAR+CHPUNC,0					;{	173
	XWD	CHPUNC,0					;|	174

;THE 3 HIGH SPECIALS
	XWD	CHSPO+CHRIA+CHEPAR+CHALT+CHPUNC,RIALT		;}      175
	XWD	CHSPO+CHRIA+CHEPAR+CHALT+CHPUNC,RIALT		;~      176
;[arpa]	XWD	CHSPO+CHBRK+CHRIA+CHDEL+CHPUNC,RIDEL		;   DEL 177
	XWD	chsusp+CHSPO+CHBRK+CHRIA+CHDEL+CHPUNC,RIDEL	;[arpa] DEL 177
TTPWID:	POINT	8,TCRTAB(T1),7	;POINTER TO TERMINAL WIDTH
TTPPSZ:	POINT	6,TCRTAB(T1),13	;POINTER TO PAGE SIZE
TTPFLC:	POINT	2,TCRTAB(T1),35	;POINTER TO DEFAULT FILL CLASS
TTPFRM:	POINT	1,TCRTAB(T1),14	;ON IF TERMINAL HAS HARDWARE FORM FEEDS
TTPTAB:	POINT	1,TCRTAB(T1),15	;ON IF TERMINAL HAS HARDWARE TABS
TTPLCT:	POINT	1,TCRTAB(T1),16	;ON IF TERMINAL DOESN'T HAVE LOWER CASE CHARACTERS
TTPALT:	POINT	1,TCRTAB(T1),17	;ON IF NO ALTMODE CONVERSION IS REQUIRED
TTPDIS:	POINT	1,TCRTAB(T1),18	;ON IF "DISPLAY" TERMINAL (E.G., FOR DDT)

DEFINE	TERMCR(NAME,WIDTH,LENGTH,FF$,TAB$,LC$,ALT$,DIS$,FILL,BPERAS,BPRUBO),<
X1==0
IFIDN <FF$><FF>,<X1==1>
X2==0
IFIDN <TAB$><TAB>,<X2==1>
X3==1
IFIDN <LC$><LC>,<X3==0>
X4==1
IFIDN <ALT$><ALT>,<X4==0>
X5==0
IFIDN <DIS$><DIS>,<X5==1>
IFNDEF TT'NAME,<TT'NAME:>BYTE	(8)WIDTH(6)LENGTH(1)X1(1)X2(1)X3(1)X4(1)X5(15)0(2)FILL
	XWD	BPERAS,BPRUBO	;<CR> EOL,,B.S. SPACE B.S.
>
CTCTAB:			;CUSTOMER TERMINAL CHARACTERISTICS GO HERE
TERMCR	LA34,↑D132,0,NOFF,TAB,LC,NOALT,NODIS,0,0,0
TERMCR	HP2621,↑D80,↑D24,FF,NOTAB,LC,NOALT,DIS,0,HP26EP,VTXXBP	;[hp2621]
TERMCR	DM1500,↑D80,↑D24,FF,TAB,LC,NOALT,DIS,0,DM15EP,VTXXBP	;[dm1500]
TCRTAB:			;SEE TTTWDT IN COMCON
TERMCR	TTY,↑D72,0,NOFF,NOTAB,NOLC,ALT,NODIS,1,0,0
TERMCR	VT05,↑D72,↑D20,NOFF,TAB,NOLC,NOALT,DIS,2,VT06EP,VTXXBP
TERMCR	VT06,↑D72,↑D25,NOFF,NOTAB,NOLC,NOALT,DIS,1,VT06EP,VT06BP
TERMCR	VT50,↑D80,↑D12,NOFF,TAB,NOLC,NOALT,DIS,0,VTXXEP,VTXXBP
TERMCR	VT52,↑D80,↑D24,NOFF,TAB,LC,NOALT,DIS,0,VTXXEP,VTXXBP
TERMCR	VT61,↑D80,↑D24,NOFF,TAB,LC,NOALT,DIS,0,VTXXEP,VTXXBP
TERMCR	DAS21,↑D80,↑D24,NOFF,TAB,LC,NOALT,DIS,0,VTXXEP,VTXXBP
TERMCR	VT100,↑D80,↑D24,NOFF,TAB,LC,NOALT,DIS,0,V100EP,VTXXBP
TERMCR	TY33,↑D72,0,NOFF,NOTAB,NOLC,ALT,NODIS,1,0,0
TERMCR	TY35,↑D72,0,FF,TAB,NOLC,ALT,NODIS,1,0,0
TERMCR	LA30,↑D72,0,NOFF,NOTAB,NOLC,NOALT,NODIS,1,0,0
TERMCR	LA36,↑D132,0,NOFF,NOTAB,LC,NOALT,NODIS,0,0,0
TERMCR	2741,↑D128,0,NOFF,NOTAB,LC,NOALT,NODIS,3,0,0
TERMCR	LA38,↑D132,0,NOFF,TAB,LC,NOALT,NODIS,0,0,0
TERMCR	LA120,↑D132,0,FF,TAB,LC,NOALT,NODIS,0,0,0
TERMCR  VT125,↑D80,↑D24,NOFF,TAB,LC,NOALT,DIS,0,V100EP,VTXXBP
TERMCR  VK100,↑D80,↑D24,NOFF,TAB,LC,NOALT,DIS,0,V100EP,VTXXBP
TERMCR  VT101,↑D80,↑D24,NOFF,TAB,LC,NOALT,DIS,0,V100EP,VTXXBP
TERMCR  VT102,↑D80,↑D24,NOFF,TAB,LC,NOALT,DIS,0,V100EP,VTXXBP
;ROUTINE TO CHECK FOR A SPECIAL CHARACTER AND SET T1 TO ITS DESCRIPTOR
;ENTER WITH T3 SET UP
;SKIPS IF CHAR IS 0-37 OR 175-177
;IGNORES AND DOES NOT RETURN PARITY BIT (CHEPAR)


SPCHEK::MOVE	T1,T3		;COPY CHAR
	ANDI	T1,177		;CLEAR PARITY
	TRNE	T3,400
	TDZA	T1,T1
	MOVE	T1,CHTABL(T1)	;GET TABLE ENTRY
	TLZ	T1,CHEPAR+CHPUNC;CLEAR PARITY AND PUNCTUATION BIT
	SKIPE	T1		;SPECIAL?
	AOS	(P)		;YES--SKIP
	POPJ	P,		;RETURN


;SUBROUTINE TO GET EVEN PARITY USING CHEPAR BIT OF CHTABL
;CALLED FROM SCNSER,PTPSER AND IN ONCE

;CALLING SEQUENCE:  PUSHJ	P,PEVEN8

;ON ENTRY, T3 CONTAINS A CHARACTER IN BITS 28 TO 35,
; BITS 0 TO 27 ARE IGNORED

;ON EXIT, BIT 28 IS CHANGED IF NECESSARY SUCH THAT THE PARITY
; OF BITS 28 TO 35 IS EVEN, AND BITS
; 0 TO 27 ARE ALL 0

PEVEN8::ANDI	T3,177		;CLEAR TO 7 BITS FOR INDEX
	PUSH	P,T1		;SAVE T1
	MOVE	T1,CHTABL(T3)	;GET CHARACTER TABLE ENTRY
	TLNN	T1,CHEPAR	;ALREADY EVEN
	TRO	T3,200		;WAS NOT, PUT IN PARITY BIT
	JRST	TPOPJ		;RESTORE T1 AND RETURN
	SUBTTL	CHUNK HANDLERS

;The routines NEWCKI and NEWCKO are provided only to support the
;macros LDCHK, LDCHKR, and STCHK.  They should not be called directly
;because they depend on the instruction following the call to be a 
;byte instruction that references the byte pointer into the chunk
;string.

;NEWCKO -- ROUTINE TO ADVANCE TO THE NEXT CHUNK WHEN PUTTING CHARACTERS
;	  INTO THE TERMINAL BUFFER CHUNKS.

NEWCKO::PUSH	P,@(P)		;SAVE ADDRESS OF THE BYTE INSTRUCTION
	HRRZ	T2,@(P)		;ADDRESS OF LAST BYTE IN CHUNK
	MOVEI	T2,CK.BTH##(T2)	;ADDRESS OF CURRENT CHUNK HEADER
	HRRZ	T1,(T2)		;IS THERE A CHUNK THERE YET?
	JUMPN	T1,[EXCH T1,T3
		    PUSHJ P,RCCCHK
		    EXCH T1,T3
		    JRST NWCKO1]
	PUSHJ	P,GETCHK	;ALLOCATE A CHUNK FROM FREE LIST
	HRLZM	T2,(T1)		;BACK POINTER TO EXISTING LIST
	HRRM	T1,(T2)		;FORWARD POINTER TO NEW CHUNK
NWCKO1:	ADD	T1,[POINT 9,1]	;MAKE A BYTE POINTER
	MOVEM	T1,@(P)		;STORE IN STRING POINTER
	SUB	P,[1,,1]	;PRUNE PUSH DOWN LIST
	POPJ	P,		;AND RETURN

;NEWCKI -- ROUTINE TO ADVANCE TO THE NEXT CHUNK WHEN TAKING CHARACTERS
;	   OUT OF THE TERMINAL CHUNKS.  USES T2 AND T3.

NEWCKI::PUSH	P,@(P)		;SAVE ADDRESS OF THE BYTE INSTRUCTION
	HRRZ	T3,@(P)		;ADDRESS OF LAST BYTE
	MOVEI	T1,CK.BTH##(T3)	;ADDRESS OF CHUNK HEADER
	HRRZ	T3,CK.BTH##(T3)	;FORWARD CHUNK POINTER
	PUSHJ	P,RCCCHK
	HRRZS	(T3)		;CLEAR BACK POINTER
	PUSHJ	P,FRECHK	;FREE UP THE STALE CHUNK
	ADD	T3,[POINT 9,1]	;MAKE FORWARD POINTER INTO A BYTE PTR
	MOVEM	T3,@(P)		;STORE IT BACK IN POINTER WORD
	SUB	P,[1,,1]	;PRUNE PUSH DOWN LIST
	POPJ	P,		;AND RETURN
;NEWCKS -- ROUTINE TO ADVANCE TO THE NEXT CHUNK WHEN TAKING CHARACTERS
;	   OUT OF THE TERMINAL CHUNKS.  DIFFERS FROM NEWCKI IN THAT THE
;	   STALE CHUNKS ARE NOT DELETED.

NEWCKS:	PUSH	P,@(P)		;SAVE ADDRESS OF THE BYTE INSTRUCTION
	HRRZ	T3,@(P)		;ADDRESS OF LAST BYTE
	MOVEI	T1,CK.BTH##(T3)	;ADDRESS OF CHUNK HEADER
	HRRZ	T3,CK.BTH##(T3)	;FORWARD CHUNK POINTER
	PUSHJ	P,RCCCHK
	ADD	T3,[POINT 9,1]	;MAKE FORWARD POINTER INTO A BYTE PTR
	MOVEM	T3,@(P)		;STORE IT BACK IN POINTER WORD
	SUB	P,[1,,1]	;PRUNE PUSH DOWN LIST
	POPJ	P,		;AND RETURN

CL0STP:	STOPCD .,STOP,CL0,	;++CHUNK LINKS TO ZERO

RCCCHK:	PUSH	P,T3		;SAVE ALL
	CAML	T3,TTBASE	;IF TOO LARGE
	CAMLE	T3,RCCMAX##	; OR TOO SMALL
	PUSHJ	P,RCCSTP	;
	ANDI	T3,CK.BDY	;JUST OFFSET WITHIN CHUNK
	CAIE	T3,1		;MUST BE ONE
	PUSHJ	P,RCCSTP	;ISN'T, DIE
	HLRZ	T3,@(P)		;ADDRESS OF PREDECESSOR
	HRRZ	T3,(T3)		; SHOULD POINT TO US
	CAME	T3,(P)		;...
	PUSHJ	P,RCCSTP	;DOESN'T, CHUNKS AE MESSED UP
	JRST	T3POPJ##	;RESTORE T3 AND RETURN
	SUBTTL	CHUNK HANDLERS -- ALLOCATION AND DEALLOCATION

;FRECHK and GETCHK are called to return and fetch chunks from the
;SCNSER chunk free chain.  The chain is maintained in first-in first-out
;order in order to preserve as much information for crash analysis as
;possible.  The oldest chunk is pointed to by TTFTAK, while the youngest
;is pointed to by TTFPUT.  To aid in reconstruction of the events
;leading to a crash, the left half of each chunk header contains the LDB
;address of the line that last used it.

GETCKZ:	PUSHJ	P,GETCHK	;GET A FREE CHUNK
	SETZM	(T1)		;ZERO THE LINK WORD
	POPJ	P,		; AND RETURN

GETCHK:	SKIPN	T1,TTFTAK	;CHECK THE FREE LIST
	STOPCD	.,STOP,FLE,	;++FREE LIST EMPTY
	PUSH	P,T2		;SAVE T2
	HRRZ	T2,(T1)		;TO NEXT CHUNK
	MOVEM	T2,TTFTAK	;STORE POINTER TO NEW FIRST CHUNK
	SOS	TTFREN##	;COUNT DOWN NUMBER OF FREE CHUNKS
	JUMPN	T2,T2POPJ##	;IF NOT LAST CHUNK, RETURN
	MOVEI	T2,TTFTAK	;MAKE TTFPUT POINT AT TTFTAK SO
	MOVEM	T2,TTFPUT	; FRECHK WILL RELINK THE POINTERS CORRECTLY
	JRST	T2POPJ##	; AND RETURN

FRECHK:	HRLZM	U,(T1)		;MARK LINE NUMBER IN CHUNK
	HRRM	T1,@TTFPUT	;STORE CHUNK AT END
	HRRZM	T1,TTFPUT	;POINT TO NEW ENTRY.
	AOS	TTFREN##	;COUNT UP NUMBER OF CHUNKS
	POPJ	P,
	SUBTTL	CHUNK HANDLERS -- CLEAR BUFFERS

;ROUTINES TO CLEAR INPUT AND OUTPUT BUFFERS

TSETBI::TRNN	U,-1
	STOPCD	.,STOP,LNS,	;++LINE NOT SETUP
	PUSHJ	P,STOPCM
	SCNOFF
TSETI2:	SETZM	LDBTIC(U)	;CLEAR COUNTS
	SETZM	LDBECC(U)	;OF INPUT CHARACTERS
	MOVE	T1,LDBTIT(U)	;MOVE PUTTERS BACK TO TAKER
	MOVEM	T1,LDBTIP(U)
	MOVEM	T1,LDBECT(U)	;NO ECHOING EITHER
	SETZM	LDBBKU(U)
	SETZM	LDBBKC(U)	; ..
	MOVEI	T1,L2RECS	;CLEAR BIT IN LDB WHICH
	ANDCAM	T1,LDBBY2(U)	; MIGHT CAUSE A LINE TO BE SKIPPED
	SCNON
	PJRST	CHKXON		;CHECK IF AN XON MUST BE SENT OUT AND EXIT

TSETBO::
IFN FTTPAG,<
	MOVSI	T1,LDLSTP+LDLSSO;CLEAR OUTPUT STOP BIT
	ANDCAM	T1,LDBDCH(U)	;OUTPUT CAN NOW HAPPEN AGAIN
>
	SCNOFF			;NO PI'S HERE
IFN FTMIC&FTMLOG,<
	SKIPE	LDBLOT(U)
	JRST	MICLGC
> ;END OF FTMLOG CONDITIONAL
	SETZM	LDBTOC(U)	;NO OUTPUT CHARACTERS LEFT
	MOVE	T1,LDBTOT(U)	;PUT PUTTER BACK AT TAKER
	MOVEM	T1,LDBTOP(U)	; ..
	MOVEI	T3,-1(T1)	;ADDRESS PART OF POINTER
	TRZ	T3,CK.BDY	;ADDRESS OF CHUNK HEADER MINUS ONE.
	HRRZ	T1,1(T3)	;ADDRESS OF FIRST CHUNK IN CHAIN TO DELETE
	JUMPE	T1,TSETB2	;IF NULL CHAIN
	SETZM	1(T3)		;CLEAR POINTER TO CHAIN BEFORE DELETION
TSETB1:	HRRZ	T3,(T1)		;POINTER TO CHUNK FOLLOWING CURRENT
	PUSHJ	P,FRECHK	;DELETE ONE CHUNK
	MOVEI	T1,(T3)		;NEXT CHUNK ON CHAIN
	JUMPN	T1,TSETB1	;LOOP TO END OF CHAIN
TSETB2:
	SCNON			;ALL'S CLEAR NOW
	MOVEI	T3,3		;ISR CODE FOR CHAR GOBBLER
	MOVEI	T1,ISRREM	;SPECIAL ISR ENTRY FOR REMOTES
	PJRST	@LDBISR(U)	;SEND MESSAGE TO CLEAR OUTPUT BUFFER IN REMOTE

RCCSTP:	STOPCD	.,STOP,RCC,	;++RANGE CHECKED CHUNK
	SUBTTL	UUO LEVEL ROUTINES FOR BUFFERED I/O

;DISPATCH TABLE FOR UUO'S AND INITIALIZATION

	JRST	ECOD2##		;NO DEVOP FUNCTIONS
	JRST	REGSIZ##	;BUFFER SIZE CAN BE GOTTEN FROM DDB
	JRST	TTYINI##(P2)	;INITIALIZATION (140 RESTART)
	JRST	CPOPJ1##	;HUNG DEVICE (NEVER USED)
SCNDSP::JRST	TTYREL		;RELEASE
	JRST	OUT##		;CLOSE OUTPUT
	JRST	TTYOUT		;TTY OUTPUT UUO
;	JRST	TTYIN		;TTY INPUT UUO
;FALL INTO TTYIN
;INPUT UUO PROCESSOR - CALLED FROM UUOCON ON INPUT UUO, DDB SET UP


TTYIN:	PUSHJ	P,SAVE3##	;SAVE P1-P3
	PUSHJ	P,CKATTI	;MAKE SURE ATTACHED. SET S.
	MOVEI	T1,DEPAIO	;IS THIS TERMINAL IN ASYNC INPUT
	TDNN	T1,DEVAIO(F)	; MODE?
	JRST	TTYINA		;NO--FORGE AHEAD
	PUSHJ	P,TTICHK	;IS THERE ANY INPUT AVAILABLE?
	  POPJ	P,0		;NO--RETURN NOW
TTYINA:	TRNN	S,I		;IMAGE MODE?
	JRST	TTYIN0		;NO. SKIP SETUP STUFF
	TRNN	S,IODERR	;EOF DUE TO ↑C ON UNATTACHED LINE?
	TLNE	S,FRCEND	;CLOCK ROUTINE WANT IT FINISHED?
	JRST	TTYIN9		;YES. GO DO SO.
	MOVE	T1,DEVMOD(F)	;IS THIS GUY ALLOWED IMAGE MODE INPUT?
	TRNN	T1,ASSCON	;I.E., HE HAS TERMINAL ASSIGNED?
	JRST	TTYINE		;NO. ERROR BIT TO USER.
	MOVSI	T1,LDLIMI	;YES. SET IMAGE INPUT IN LINE DATA
	IORM	T1,LDBDCH(U)	; ..
	PUSHJ	P,SETCHP	;MAKE SURE THAT THE FRONT END KNOWS
TTYIN0:	PUSHJ	P,TWAITI	;BECOME ATTACHED, WAIT FOR INPUT
				; OR FULL BUFFER CONDITION
	TLNE	S,FRCEND	;DID WE TIME OUT AT CLOCK
	JRST	TTYIN9		;LEVEL WHILE WAITING ?
TTYIN5:	HRRZ	T1,DEVIAD(F)	;PREPARE AND ADDR CHECK THE
	PUSHJ	P,BUFCLR##	; USER'S BUFFER
	  JRST ADRERR##		;OUT OF BOUNDS. STOP JOB.
	HRRZ	P1,DEVIAD(F)	;USER VIRTUAL ADDRESS OF BUFFER
	EXCTUX	<LDB P2,[POINT 17,@P1,17]>  ;SIZE OF BUFFER (DATA + 1)
	SUBI	P2,1		;LESS THE .BFCNT WORD
	HRRZ	U,DDBLDB(F)	;RESTORE LINE, CLOBBERED IN UUOCON
	PUSHJ	P,SRLPTR	;SETUP BYTE COUNT AND POINTER
	PUSH	P,P2		;SAVE BYTE COUNT
				;FALL INTO MAIN PART OF ROUTINE
TTYIN1:	PUSHJ	P,TYICC		;GET A CHARACTER
	  JRST TTYIN3		; END OF BUFFER.
	MOVE	P3,T3		;COPY CHARACTER
	ANDI	P3,377		;STRIP IMAGE BIT
	EXCTUU	<IDPB P3,P1>	;AND STORE IN USER AREA
	TRNN	S,I!PIMMOD	;SKIP IF IMAGE MODE OF SOME SORT
	JRST	TTYIN2		;NO, ASCII MODE
	SOJG	P2,TTYIN1	;YES, JUST FILL BUFFER
	JRST	TTYIN3		;BUFFER FULL, GIVE IT TO THE USER

TTYIN2:	TLNN	T1,CHBRK	;A BREAK?
	SOJG	P2,TTYIN1	;NO. LOOP FOR MORE, IF ROOM.
	MOVSI	S,IOEND		;COUNTED OUT, OR BREAK.
	MOVE	T1,DEVIOS(F)	;GET USER MODE BITS
	TRZ	T3,200		;STRIP OFF PARITY, NOT IMAGE.
	TRNN	T1,IOSTEC	;TRUTH-IN-ECHOING MODE AND
	CAIE	T3,"Z"-100	;END OF FILE CHARACTER?
	MOVEI	S,0		;NO. NOT EOF.
	IORB	S,DEVIOS(F)	;STORE IN DDB S WORD
TTYIN3:	POP	P,T1		;GET BACK ORIGINAL MAX BYTE COUNT
	TRNN	S,PIMMOD	;BYTE COUNT IF PIM
	SKIPA	P2,DEVIAD(F)	;NOT PIM - BUFFER PTR IN P2
	SKIPA			;PIM - DON'T DESTROY BYTE COUNT
	JRST	TTYINC		;NOT PIM-WORD COUNT
	MOVN	P1,P2		;COUNT OF BYTES LEFT
	ADD	P1,T1		;FROM MAX = COUNT OF BYTES DEPOSITED
	SKIPA	P2,DEVIAD(F)	;ALREADY HAVE COUNT IN P1
TTYINC:	SUBI	P1,1(P2)	;COMPUTE WORD COUNT FOR UUOCON
	EXCTUU	<HRRM P1,1(P2)>	;STORE WITH DATA IN RING
	PUSHJ	P,ADVBFF##	;ON TO NEXT BUFFER
	  JRST	TTYIN8		;NO MORE BUFFERS AVAILABLE
	TRNE	S,I!PIMMOD	;IMAGE MODE?
	SKIPG	LDBTIC(U)	;AND MORE CHARACTERS TO READ?
	JRST	TTYIN8		;NO - ASCII, ONLY PASS ONE LINE AT A TIME
	JRST	TTYIN5		;YES. GO PASS SOME MORE

TTYIN8:	MOVSI	S,IOFST		;SET VIRGIN BUFFER BIT
TTYINX:	IORB	S,DEVIOS(F)	;IN DEV S WORD IN DDB
	HRRZ	U,DDBLDB(F)
	JUMPE	U,CPOPJ##
	PJRST	NOCTRO		;CLEAR CONTROL O. END OF UUO

;HERE IF ATTEMPT TO PUT UNASSIGNED TERMINAL IN IMAGE INPUT STATE

TTYINE:	MOVEI	S,IOIMPM
	JRST	TTYINX		; AND RETURN

TTYIN9:	MOVSI	S,IOEND		;SET END OF FILE BIT IN S
	JRST	TTYINX
;OUTPUT UUO CALLS HERE

;CALLED ON OUTPUT OR OUTPUT CLOSE, FROM UUOCON, WITH DDB SET UP.


TTYOUT:	PUSHJ	P,SAVE2##	;SAVE P1-P2
IFN FTRSP,<PUSHJ P,RSPTOR##>	;RECORD RESPONSE SATISFIED BY TERMINAL OUTPUT
	TRNE	S,IODERR	;↑C TYPED AT TTYNNN
	JRST	TTOUT3		;YES, RETURN
	PUSHJ	P,CKATOU	;FIRST, MAKE SURE THERE'S A
				; PHYSICAL LINE ATTACHED TO JOB, AT USER LEVEL
	TRNN	S,I		;UNLESS IMAGE MODE,
	PUSHJ	P,CLRIMI	;CLEAR IMAGE INPUT STATE
	MOVSI	S,IOBEG		;IS THIS THE FIRST BUFFER AFTER INIT?
	TDNN	S,DEVIOS(F)	;CHECK DDB
	JRST	TTOUT1		;NO.
	ANDCAM	S,DEVIOS(F)	;YES. CLEAR BEG BIT,
	PUSHJ	P,NOCTRO	; AND CONTROL O
TTOUT0:	SETZM	DEVSTS(F)	;CLEAR OLD PARTIAL BYTE POINTER IF ANY

;OUTPUT A BUFFER OF TEXT. AT THIS POINT WE COULD CHECK FOR ↑O IN EFFECT
;AND JUST EAT THE BUFFER, BUT WE DON'T WANT ↑O TO BE TOO FAST . . .

TTOUT1:	MOVE	S,[IO!IOFST,,IOACT]	;MARK START OF NEW OUTPUT
	IORB	S,DEVIOS(F)	;IN DEVICE DATA BLOCK
	HRRZ	P1,DEVOAD(F)	;USER VIRTUAL ADDRESS OF OUTPUT BUFFER
	HRRZ	T1,P1		;CHECK ADDRESSES OF OUTPUT BLOCK
	PUSHJ	P,BRNGE##	;MAKE SURE BUFFER IS ADDRESSABLE
	EXCTUX	<HRRZ P2,1(P1)>	;SIZE OF DATA AREA (WORDS) TO BE OUTPUT
	JUMPE	P2,TTOUT6	;SKIP THIS BUFFER IF EMPTY
	EXCTUX	<LDB T1,[POINT 17,@P1,17]>  ;GET TOTAL BUFFER SIZE
	CAML	P2,T1		;DATA CONTAINED WITHIN BUFFER?
	JRST	TTYINE		;NO, USER BLEW IT
				; (IT ALSO MIGHT IME US!)
	PUSHJ	P,SRLPTR	;GET BYTE COUNT AND POINTER
	SKIPN	DEVSTS(F)	;OUTPUT PENDING?
	JRST	TTOUT2		;NO, NEW BUFFER
	MOVE	P1,DEVSTS(F)	;YES, GET LAST OUTPUT POINTER
	LDB	P2,BYTCNT	;AND REMAINING BYTE COUNT
				; AND FINISH (MAYBE) OUTPUTTING THE BUFFER

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;LOOP OUTPUTTING CHARACTER FROM THE USER BUFFER

TTOUT2:	PUSHJ	P,CKROOM	;SEE IF WE SHOULD CALL TYO
	  JRST	TTOUT7		;IO WAIT WOULD HAPPEN
	MOVE	T3,P1		;COPY BYTE POINTER
	EXCTUX	<ILDB T3,T3>	;INCREMENT THIS COPY, GET USER'S CHAR
	ANDI	T3,377		;KEEP JUST THE CHARACTER
	TRNE	S,I!PIMMOD	;SEE IF IMAGE MODE OR PIM
	TROA	T3,400		;YES.  SET BIT FOR SUPPRESSING FILLERS
	JUMPE	T3,TTOUT4	;DON'T OUTPUT NULLS
	MOVEI	T1,DEPAIO	;IF DOING ASYNCHRONOUS I/O,
	TDNE	T1,DEVAIO(F)	; TELL TYO NOT TO BLOCK SINCE
	TLO	T3,(1B0)	; WE MAY BE HERE FORM TTMORE
	TRNE	S,IODERR	;↑C TYPED ON TTYNNN
	JRST	TTOUT3		;YES, RETURN
	PUSHJ	P,TYO9W		;OUTPUT THIS CHARACTER (WAIT IF NEEDED)
	JUMPL	T3,TTOUT7
TTOUT4:	IBP	P1
TTOUT5:	SOJG	P2,TTOUT2	;COUNT USER'S ITEMS.
TTOUT6:	PUSHJ	P,ADVBFE##	;ADVANCE HIS BUFFERS
	  JRST	TTOUT3		;JUST SINGLE BUFFER FOR NOW
	MOVEI	T1,DEPAIO	;NON-BLOCKING I/O BIT
	TDNE	T1,DEVAIO(F)	;DOING NON-BLOCKING I/O
	JRST	TTOUT0		;YES, START THE NEXT BUFFER OUT
TTOUT3:	SETZM	DEVSTS(F)
	MOVEI	S,IOACT		;CLEAR ACTIVE BIT.
	ANDCAB	S,DEVIOS(F)	;IN DEVICE DATA BLOCK FOR THE JOB
	POPJ	P,0		;END OF UUO. RETURN TO USER

TTOUT7:	MOVEM	P1,DEVSTS(F)	;SAVE THE INTERRUPTED BYTE POINTER
	DPB	P2,BYTCNT	; AND ITS COUNTER
TTOUT8:	MOVEI	T1,JS.NTO	;SET THE MAGIC
	IORM	T1,JBTSTS##(J)	; BIT IN JBTSTS
	MOVEI	S,IOACT		;CLEAR I/O ACTIVE BIT
	ANDCAB	S,DEVIOS(F)	;..
	POPJ	P,0		;RETURN
TTMORE::PUSHJ	P,SAVE2##	;SAVE P1-P2
	MOVEI	F,SCNDDB	;FIRST DDB
	MOVEI	P2,JS.NTO	;FLAG RESET
	MOVE	T1,.CPPC##	;GET THE CURRENT PC
	TLNE	T1,USRMOD	;IN USER MODE?
	MOVEM	T1,.JDAT+JOBPD1##	;YES--MAKE SURE JOBPD1 IS RIGHT
MORE10:	LDB	T1,PJOBN##	;GET OWNER
	CAIN	T1,(J)		;IS IT THIS JOB?
	SKIPN	DEVSTS(F)	;IS OUTPUT WAITING?
	JRST	MORE20		;NO, TRY NEXT DDB
	MOVEI	T1,DEPAIO
	TDNN	T1,DEVAIO(F)	;NON-BLOCKING I/O ON THIS TERMINAL?
	JRST	MORE20		;NO, LOOK AT OTHER TERMINALS
	PUSHJ	P,MORE30	;GO TRY OUTPUT
	MOVEI	P2,0		;FLAG ONE ACTIVE
MORE20:	HLRZ	F,DEVSER(F)	;PICK UP NEXT DDB
	MOVSI	T1,DVTTY	;IS THIS A TTY?
	TDNE	T1,DEVMOD(F)	; ..
	JUMPN	F,MORE10	;YES--LOOK AT IT TOO
	ANDCAM	P2,JBTSTS##(J)	;CLEAR THE STATUS
	POPJ	P,0		;RETURN
MORE30:	HRRZ	U,DDBLDB(F)	;GET ADDRESS OF LDB
	JUMPE	U,CPOPJ##	;PUNT IF DETACHED
	MOVE	S,DEVIOS(F)	;SET UP S FOR TYO
	LDB	P1,BYTCNT	;GET THE BYTE COUNT
	JUMPE	P1,MORE41	;IF BYTE COUNT=0 AND DEVSTS NON-0, BUFFER WASN'T ADVANCED
				; BECAUSE WHAT DEVOAD POINTED TO WAS PAGED OUT

MORE40:	PUSHJ	P,CKROOM	;ROOM FOR MORE DATA?
	  JRST	[DPB P1,BYTCNT	;NO--SAVE BYTE COUNT
		 POPJ P,0]	;RETURN
	MOVE	T1,DEVSTS(F)	;GET POINTER
	IBP	T1		;UPDATE POINTER
	MOVE	T3,T1		;COPY BYTE POINTER
	TLZ	T1,-1		;CLEAR JUNK
	PUSHJ	P,IADRCK##	;MAKE SURE ITS LEGAL AND IN CORE
	  JRST	MORE50
	EXCTUX	<LDB T3,T3>	;GET NEXT BYTE
	TRNE	S,I!PIMMOD	;IF IMAGE OR PIM
	TROA	T3,400		;FLAG IT
	JUMPE	T3,MOR405	;SKIP CALL IF NO CHARACTER
	TLO	T3,(1B0)	;DON'T BLOCK IN TYO
	PUSHJ	P,TYO9W		;TYPE IT
	JUMPGE	T3,MOR405	;PROCEED IF CHAR OUTPUT
	DPB	P1,BYTCNT	;ELSE REMEMBER WHERE
	JRST	TTOUT8		;WE WERE & RETURN
MOR405:	IBP	DEVSTS(F)	;INCREMENT PRIME COPY
	SOJG	P1,MORE40	;DO THE NEXT BYTE
MORE41:	HRRZ	T1,DEVOAD(F)	;BUF APR
	SOS	T2,T1		;WORD-1
	ADDI	T2,3		;THRU WORD1
	PUSHJ	P,ZRNGE##	;IN CORE?
	  JRST	MORE50		;NO

IFN FTPI,<
	TLO	S,IO		;FORCE FLAG TO OUTPUT
	PUSHJ	P,PSIIOD##
>
	JRST	TTOUT6		;ALL DONE
MORE50:	DPB	P1,BYTCNT	;SAVE BYTE COUNT
	MOVE	T3,.CPPC##	;JOB'S PC
	TLNN	T3,USRMOD	;IN USER MODE?
	POPJ	P,		;NO, TRY AGAIN LATER
	MOVE	T3,[EXP IC.UOU+TTYFLT##]
	MOVEM	T3,.CPPC##	;GO TO TTYFLT
	MOVEM	T1,.UPMP+.UPUPF	;STORE FAULT ADDRESS
	POPJ	P,


CKROOM:	MOVEI	T1,DEPAIO	;IF THIS JOB IS NOT USING
	TDNN	T1,DEVAIO(F)	; ASYNCHRONOUS I/O THEN
	JRST	CPOPJ1##	; JUST GIVE THE SKIP RETURN
	SKIPLE	T1,TTFREN##	;GET THE FREE CHUNK COUNT
	CAIG	T1,5		;ENOUGH ROOM?
	POPJ	P,0		;NO--QUIT NOW
	MOVE	T1,LDBTOC(U)	;GET OUTPUT BYTE COUNT
	ADDI	T1,↑D25		;REDUCE ODDS OF LOSSAGE
	CAMG	T1,TIWRNN	;TOO MUCH STUFF?
	AOS	(P)		;NO--CALL TYO
	POPJ	P,0		;RETURN
	SUBTTL	DDT MODE CALLI'S

;INPUT TO DDT	- CALL AC,[SIXBIT /DDTIN/]  WHERE AC/ ADDR
;ADDR GETS UP TO 21 WORDS OF ASCIZ, BREAKING ON ANY CHARACTER

DDTIN::	PUSHJ	P,SAVE3##	;SAVE P1-P3 (TYICC KRUMPS P3)
	PUSHJ	P,TTYFNU	;SET LINE AND DDB FOR THIS TTY
	PUSHJ	P,CKATTI	;MAKE SURE TERMINAL ATTACHED
	PUSHJ	P,GETWDU##	;DO ADDRESS CHECKING FIRST
	HRRZS	T1
	PUSHJ	P,IADRCK##	; ..
	  JRST	ADRERR##	;NO GOOD
	ADDI	T1,21		;CHECK END OF AREA
	PUSHJ	P,IADRCK##	; ..
	  JRST	ADRERR##	;NO GOOD
	MOVSI	P1,440700	;SEVEN BIT BYTES, RELOCATED.
	HRRI	P1,-21(T1)	;IN USER AREA
	MOVEI	P2,<21*5>-1	;NUMBER OF BYTES ALLOWED
	PUSHJ	P,TWAITC	;GET AT LEAST ONE CHARACTER
DDTINL:	SKIPG	LDBTIC(U)	;ANY MORE TO COME?
	JRST	DDTINX		;NO.
	PUSHJ	P,TYICC		;YES. GO GET ONE
	  JRST	DDTINX		;WASNT ANY. I'M CONFUSED.
	TRNE	T3,177		;NULL?
	EXCTUU	<IDPB T3,P1>	;NO. STORE IN USER AREA
	SOJG	P2,DDTINL	;IF MORE SPACE, GET ANOTHER CHARACTER
DDTINX:	MOVEI	T3,0		;FLAG END OF STRING
	EXCTUU	<IDPB T3,P1>	; IN USER AREA
	PJRST	NOCTRO		;AND RETURN TO USER, CLEARING ↑O FLAG

;DDTOUT - CALL AC,[SIXBIT /DDTOUT/], AC/ ADDR, ADDR/ ASCIZ /XXX/

DDTOUT::HRR	M,T1		;USER ADR. OF TEXT TO M
	PUSHJ	P,TTYFNU	;GET USER'S CONSOLE
	PUSHJ	P,CKATOU	;MAKE SURE AT USER LEVEL AND ATTACHED
	JRST	OUTSTR		;SAME AS THE CORRESPONDING TTCALL
	SUBTTL	TTCALL AND TRMOP. -- TTCALL DISPATCH

;TTCALL AC,E - VALUE OF AC DETERMINES ACTION OF UUO (051)

TTYUUO::PUSHJ	P,SAVE2##	;SAVE P1,P2
	PUSHJ	P,TTYFNU	;FIND CURRENT USER'S TTY
	MOVE	P2,TTUUOT(P1)	;GET PRE-CHECK BITS
	TLNE	P2,TC.ATW	;ATTACH OR WAIT?
	PUSHJ	P,CKATTO	;YES.  WAIT TILL ATTACHED
TTUUA:	TLNN	P2,TC.ATR	;ATTACH OR RETURN?
	JRST	TTUUB		;NO
	TRNN	U,-1		;YES.  LINE NON-ZERO?
	POPJ	P,0		;NO.  RETURN, NO TERMINAL

TTUUB:	JUMPE	U,TTUUD		;ONE UUO-GETLCH-CAN BE HERE DETACHED
	HLL	U,LDBDCH(U)	;GET LINE DESCRIPTION
	TLNN	P2,TC.USR	;USER OR RETURN?
	JRST	TTUUC		;NO
	TLNE	U,LDLCOM	;YES.  USER LEVEL?
	POPJ	P,0		;NO.  RETURN.

TTUUC:	TLNE	P2,TC.USW	;USER OR WAIT?
	TLNN	U,LDLCOM	;YES.  AT USER LEVEL
	JRST	TTUUD		;USER LEVEL, OR NOT NEEDED
	PUSHJ	P,CKATOU	;TOP LEVEL.WAIT FOR USER.
	JRST	TTYUUO		;RESTART UUO IN CASE OF
				;ATTACH.
TTUUD:	TLNN	P2,TC.ADC	;ADDRESS CHECK NEEDED?
	JRST	TTUUE		;NO.  GO DISPATCH.
	HRRZ	T1,M		;ADDRESS TO P1, WHICH IS P1
	PUSHJ	P,UADCK1##	;CHECK THE ADDRESS
TTUUE:	TLNE	P2,TC.ECS	;INPUT OPERATION?
	PUSHJ	P,TYIEAT	;YES, EAT COMMAND IF LEFT OVER
	JRST	@TTUUOT(P1)	;DISPATCH TO ROUTINE
;THE FOLLOWING TABLE IS USED TO PRE-CHECK AND DISPATCH THE TTCALL'S.
;BITS IN THE LEFT ARE CHECKED BEFORE DISPATCHING.
;INDIRECT AND INDEX MUST BE ZERO, FOR JRST INDIRECT, BUT THIS COULD
;EASILY BE CHANGED IF THE BITS RUN OUT.


TC.ADC==400000		;THIS FUNCTION MUST BE ADDRESS CHECKED
TC.USR==200000		;THIS FUNCTION MUST BE AT USER LEVEL, ELSE POPJ
TC.USW==100000		;THIS FUNCTION MUST BE AT USER LEVEL, ELSE WAIT
TC.ATW==040000		;THIS FUNCTION MUST BE ATTACHED, ELSE WAIT
TC.ATR==020000		;THIS FUNCTION MUST BE ATTACHED, ELSE POPJ
TC.ECS==010000		;EAT COMMAND SYNC (CALL TYIEAT)
;DON'T ASSIGN BITS 13-17 WITHOUT CHANGING DISPATCH CODE

TTUUOT:	XWD	TC.ATW+TC.USW+TC.ADC+TC.ECS,INCHRW	;(00) INPUT CHARACTER, WAIT
	XWD	TC.ATW+TC.USW,ONEOUT		;(01) OUTPUT CHARACTER
	XWD	TC.ATR+TC.USR+TC.ADC+TC.ECS,INCHRS	;(02) INPUT CHARACTER, SKIP
	XWD	TC.ATW+TC.USW,OUTSTR		;(03) OUTPUT AN ASCIZ STRING
	XWD	TC.ATW+TC.USW+TC.ADC+TC.ECS,INCHWL	;(04) INPUT CHARACTER, WAIT LINE MODE
	XWD	TC.ATR+TC.USR+TC.ADC+TC.ECS,INCHSL	;(05) INPUT CHARACTER, SKIP LINE MODE
	XWD	TC.ADC,GETLIN			;(06) GET LINE CHARACTERISTICS
	XWD	TC.ATW+TC.ADC,SETLIN		;(07) SET LINE CHARACTERISTICS
	XWD	TC.ATR,TRESCU			;(10) RESCAN COMMAND LINE
	XWD	TC.ATR,TSETBI			;(11) CLEAR INPUT BUFFER
	XWD	TC.ATR,TSETBO			;(12) CLEAR OUTPUT BUFFER
	XWD	TC.ATR+TC.USR+TC.ECS,SKPINC	;(13) SKIP IF A CHAR TO BE INPUT
	XWD	TC.ATR+TC.USR+TC.ECS,SKPINL	;(14) SKIP IF A LINE TO BE INPUT
	XWD	TC.ATW+TC.USW,IONEOU		;(15) IMAGE ONE-CHARACTER OUTPUT
	XWD	0,CPOPJ##			;(16) NOT IMPLEMENTED
	XWD	0,CPOPJ##			;(17) NOT IMPLEMENTED
	SUBTTL	TTCALL AND TRMOP. -- OUTCHR AND IMAGE OUTCHR

;ONEOUT OUTPUTS ONE CHARACTER FROM C(E)

ONEOUT:	PUSHJ	P,SAVE2##	;SAVE P2
	SKIPN	F		;ANY DDB?
	SKIPA	P2,[CCTYO]	;NO--MUST BE SLOPPY
	MOVEI	P2,TYO7W	;YES--BE NEAT
IFN FTRSP,<PUSHJ P,RSPTOR##>	;RECORD RESPONSE SATISFIED BY TERMINAL OUTPUT
ONEOU1:	PUSHJ	P,GETWDU##	;PICK UP USER'S WORD
	MOVE	T3,T1		;PUT IN RIGHT AC
	ANDI	T3,177		;MASK OUT ANY JUNK
	JUMPE	T3,CPOPJ##	;IF NOT NULL,
	PJRST	(P2)		;TYPE OUT, WITH PARITY, WAIT IF NEEDED

;IONEOU OUTPUTS ONE CHARACTER FROM LOW 8 BITS OF C(E)
IONEOU:
IFN FTRSP,<PUSHJ P,RSPTOR##>	;RECORD RESPONSE SATISFIED BY TERMINAL OUTPUT
	PUSHJ	P,CLRIIQ	;NOT IN INPUT WAIT ANY MORE
	JUMPE	F,ONEOU1	;IF NO DDB, SEND 7 BITS
	PUSHJ	P,GETWDU##	;GET USER'S DATUM
	HRRZ	T3,T1		;INTO RIGHT AC
	TRO	T3,400		;FLAG AS IMAGE CHARACTER (NO FILLER)
	PJRST	TYO9W		;SEND IMAGE CHARACTER (WAIT IF NEEDED)
	SUBTTL	TTCALL AND TRMOP. -- OUTSTR AND RESCAN

;OUTSTR OUTPUTS A STRING OF ASCIZ CHARACTERS

OUTSTR:
IFN FTRSP,<PUSHJ P,RSPTOR##>	;RECORD RESPONSE SATISFIED BY TERMINAL OUTPUT
	PUSHJ	P,SAVE4##	;SAVE P1-P4
	MOVEI	P3,TYO7W
OUTST3:	LDB	T1,[POINT 9,M,26] ;PAGE #
	PUSHJ	P,TPSHS##	;IS PAGE SHARED?
	  JRST	OUTST6		;YES -- JUST USE
	HRROI	T1,(M)		;LEFT JUSTIFIED ASCIZ STRING
	PUSHJ	P,CKSTR##	;MAKE SURE ITS IN CORE AND LEGAL
	  JRST	UADERR##	;ADDRESS CHECK
OUTST6:	HRRI	M,-1(M)		;COMPENSATE FOR GETWD1
OUTST5:	MOVEI	P4,200		;MAXIMUM # OF WORDS IN ONE SHOT
OUTST2:	MOVE	P1,[POINT 7,P2]	;PREPARE TO READ BYTES
	PUSHJ	P,GETWD1##	;GET A USER'S WORD
	MOVE	P2,T1		;PUT WORD IN A SAFE AC
OUTST1:	TLNN	P1,760000	;ANY BYTES LEFT?
	JRST	OUTST4		;NO. GET ANOTHER WORD
	ILDB	T3,P1		;YES. GET ONE
	JUMPE	T3,CPOPJ##	;NULL MARKS END OF STRING
	PUSHJ	P,(P3)		;TYPE OUT CHARACTER WITH PARITY
	JRST	OUTST1		;AND GO BACK FOR MORE.

OUTST4:	SOJG	P4,OUTST2	;GO BACK FOR MORE. IS MESSAGE LONG?
	PUSHJ	P,SCDCHK##	;GIVE THE REST OF THE WORLD A CHANCE
	JRST	OUTST5

;TRESCU IS RESCAN FUNCTION FOR PROGRAM TO READ COMMAND THAT STARTED IT

TRESCU:	MOVE	T2,LDBBY2(U)	;SAVE OLD BIT FOR TEST
	MOVEI	T1,L2RECS	;CLEAR BIT IN LINE DATA BLOCK WHICH
	ANDCAM	T1,LDBBY2(U)	; WOULD CAUSE COMMAND TO BE SKIPPED
	TDNN	T2,T1		;SEE IF ANYTHING THERE
	TRNN	M,1		;NO--SEE IF USER WANTS TO KNOW
	POPJ	P,0		;NO--JUST RETURN
	JRST	CPOPJ1##	;YES--GIVE SKIP RETURN
	SUBTTL	TTCALL AND TRMOP. -- SKPINL AND SKPINC

;SKIP IF A LINE MAY BE INPUT

SKPINL:	PUSHJ	P,TYIEAT	;MAKE SURE NOT FAKED BY COMMAND
	PUSHJ	P,NOCTRO	;CLEAR THE ↑O BIT
	PJRST	TTLCHK		;CHECK FOR LINE READY
				; AND RETURN SKIP/NON-SKIP

;SKIP IF A CHARACTER MAY BE INPUT

SKPINC:	PUSHJ	P,TYIEAT	;MAKE SURE NOT FAKED BY COMMAND
	SKIPG	LDBTIC(U)	;ANY WAITING TO INPUT
	SKIPLE	LDBECC(U)	; OR WAITING FOR ECHO?
	AOS	(P)		;SAY SOMETHING'S THERE
	PJRST	NOCTRO		;AND CLEAR CTRL/O



NOCTRO:	MOVEI	T1,LDROSU	;CLEAR OUTPUT SUPPRESS BIT
	ANDCAM	T1,LDBDCH(U)	; IN LINE DATA BLOCK
	POPJ	P,0		;AND RETURN

STCTRO:	MOVEI	T1,LDROSU	;THE OUTPUT SUPPRESS BIT
	IORM	T1,LDBDCH(U)	;SET OUTPUT SUPPRESSION
	DPB	T1,LDPSVC	;CLEAR OUT ANY SAVED CHARACTER
	PJRST	TSETBO		;CLEAR OUTPUT BUFFER
	SUBTTL	TTCALL AND TRMOP. -- GETLIN


;DEFINE THE BITS FOR THE USER ARGUMENT TO GETLIN AND SETLIN

	GL.ITY==400000		;
	GL.CTY==200000		;CTY
	GL.DSP==100000		;TTY DISPLAY
	GL.DSL==040000		;DATA SET LINE
	GL.HDP==010000		;HALF DUPLEX
	GL.REM==004000		;REMOTE TTY, NO [1,2] LOGIN
	GL.RBS==002000		;NETWORK LINE
	GL.LIN==000100		;LINE OF INPUT READY
	GL.SLV==000040		;TTY SLAVE
	GL.LCM==000020		;TTY LOWER CASE
	GL.TAB==000010		;TTY TAB
	GL.LCP==000004		;TTY NO ECHO
	GL.PTM==000002		;TTY PAPER TAPE

;GETLIN RETURNS A WORD OF INFORMATION ABOUT A LINE

GETLIN:	PUSHJ	P,GETWDU##	;GET "ADDR"
	JUMPL	T1,GETLN1	;DOES HE WANT HIS OWN LINE
	TRZ	T1,.UXTRM	;CLEAR THE TTY IO INDEX BIT
	CAIL	T1,TTPLEN##	;LEGAL TTY?
	  JRST	GETLNZ		;NO, RETURN A ZERO
	MOVE	U,LINTAB##(T1)	;GET THE LDB ADDRESS

GETLN1:	JUMPE	U,GETLNZ	;NO LDB, NO BITS!
	LDB	T1,LDPLNO	;COPY THE LINE # FROM THE LDB
	TRO	T1,.UXTRM	;SET THE TERMINAL INDEX BIT

;SET BITS FROM THE (RH) OF LDBDCH(U)

	MOVE	T2,LDBDCH(U)	;GET THE CHARACTERISTICS WORD
	TRNE	T2,LDRPTY	;PTY LINE?
	  TLO	T1,GL.ITY	;YES
	TRNE	T2,LDRCTY	;CTY LINE?
	  TLO	T1,GL.CTY	;YES
	TRNE	T2,LDRDSD	;DATA SET LINE?
	  TLO	T1,GL.DSL	;YES
	TRNE	T2,LDRHLF	;HALF DUPLEX?
	  TLO	T1,GL.HDP	;YES
	TRNE	T2,LDRRMT	;NETWORK LINE?
	  TLO	T1,GL.REM	;YES
	TRNE	T2,LDRREM	;REMOTE STATION LINE?
	  TLO	T1,GL.RBS	;YES

;SET BITS FROM THE (LH) OF LDBCH(U)

	TLNE	T2,LDLSLV	;SLAVE?
	  TLO	T1,GL.SLV	;YES
	TLNN	T2,LDLLCT	;LOWER CASE TRANSLATION?
	  TLO	T1,GL.LCM	;YES
	TLNE	T2,LDLTAB	;TTY TAB?
	  TLO	T1,GL.TAB	;YES
	TLNE	T2,LDLLCP	;LOCAL COPY?
	  TLO	T1,GL.LCP	;YES

;SET BITS FROM THE (LH) OF LDBPAG(U)

	MOVE	T2,LDBPAG(U)	;GET THE PAGE MODE WORD
	TLNE	T2,LPLDIS	;DISPLAY MODE?
	  TLO	T1,GL.DSP	;YES

;SET BITS FROM THE (RH) OF LDBBY2

	MOVE	T2,LDBBY2(U)	;GET THE SECOND BYTE WORD
	TRNE	T2,L2RXON	;PAPTER TAPE MODE?
	  TLO	T1,GL.PTM	;YES

;FIND OUT IF WE HAVE A LINE OF INPUT READY

	MOVE	T3,T1		;CLOBBERS T1
	PUSHJ	P,TTLCK2	;CHECK FOR A READY LINE
	  TDZA	T1,T1		;NO LINE READY YET
	MOVSI	T1,GL.LIN	;READY BIT
	IOR	T1,T3		;A LINE IS READY
	PJRST	PUTWDU##	;GIVE RESULT TO THE USER

;HERE WHEN WE HAVE FOUND AN ERROR TO RETURN ZERO

GETLNZ:	MOVEI	T1,0		;GET A ZERO AND
	PJRST	PUTWDU		;RETURN IT TO INDICATE AN ERROR
	SUBTTL	TTCALL AND TRMOP. -- SETLIN, INCHSL, INCHWL, INCHRS & INCHRW

;ROUTINE TO SET LINE CHARACTERISTICS FOR THE CURRENT LINE (U)

SETLIN:	PUSHJ	P,GETWDU##	;GET THE BITS
	HLRZS	T1		;GET THEM IN THE RH
	SETZ	T2,		;CLEAR T2
	TRNE	T1,GL.PTM	;SET PAPER TAPE MODE?
	  MOVEI	T2,1		;YES
	DPB	T2,L2PXON	;SET THE BIT
	SETZ	T2,		;CLEAR T2
	TRNE	T1,GL.DSP	;DISPLAY MODE?
	  MOVEI	T2,1		;YES
	DPB	T2,LDPDIS	;SET THE BIT
	TRC	T1,GTLT37	;STORED AS COMPLEMENT
	ROT	T1,-2		;BIT DEPENDENT FOR DPB BELOW
	DPB	T1,SETLP1	;THESE THREE BITS CAN BE SET
	PJRST	SETCHP		;LET THE NETWORK KNOW IF WE
				;CHANGE ANYTHING

;BYTE POINTERS NEEDED BY SETLCH

L2PXON:	POINT	1,LDBBY2(U),18	;PAPER TAPE BIT

SETLP1:	POINT	3,LDBDCH(U),15	;PART OF LEGAL BITS

INCHRS:	PUSHJ	P,SKPINC	;CAN I GET A CHARACTER (CLEAR ↑O)
	  POPJ	P,0		;NO. GIVE NON-SKIP RETURN
	PUSHJ	P,TWAITC	;WAIT IN CASE NOT ECHOED YET
ICS3:	PUSHJ	P,TYIS		;GET A CHARACTER
	  JRST	NOCTRO		;NONE THERE.
	AOS	0(P)		;GIVE SKIP RETURN
	JRST	ICW1		;AND RETURN THE CHARACTER

INCHSL:	PUSHJ	P,SKPINL	;IS THERE A LINE AVAILABLE?
	  POPJ P,0		;NO. NON-SKIP RETURN TO USER
	PUSHJ	P,TWAITL
	JRST	ICS3		;YES. GO GET A CHARACTER FOR HIM

INCHWL:	PUSHJ	P,TWAITL	;WAIT FOR A LINE TO APPEAR
	PUSHJ	P,TYI		;GO GET A CHARACTER
	  MOVEI	T3,0		;IMPOSSIBLE. NO CHARACTERS. USER SET IODERR?
ICW1:	ANDI	T3,177		;MASK TO SEVEN BITS
	MOVE	T1,T3
	PUSHJ	P,PUTWDU##	;GIVE HIM THE CHARACTER
	JRST	NOCTRO		;AND NON-SKIP RETURN

INCHRW:	PUSHJ	P,TWAITC	;WAIT FOR A CHARACTER TO APPEAR
	PUSHJ	P,TYI		;GO GET THE CHARACTER
	  MOVEI	T3,0		;IMPOSSIBLE. NONE THERE. USER SET IODERR?
	JRST	ICW1		;GIVE HIM T3 AND RETURN
	SUBTTL	TTCALL AND TRMOP. -- TRMNO. UUO

;TRMNO.	CALLI, TO GET TERMINAL NUMBER
;FOR SPECIFIED JOB NUMBER.
;	MOVE	AC,JOBNUMBER
;CALL	CALLI	AC,115
;	.ERROR RETURN
;	NORMAL RETURN		;AC HAS .UXTRM+LINE#

TRMNO::	CAMN	T1,[-1]		;IS ARG -1?
	MOVEI	T1,(J)		;YES, USE THIS JOB
	JUMPLE	T1,RTZER##	;ERROR IF JOB # 0 OR LESS THAN -1
	CAMLE	T1,HIGHJB##	; OR TOO BIG
	JRST	RTZER##		;..
	HRRZ	T1,TTYTAB##(T1)	;GET DDB ADDRESS
	JUMPE	T1,RTZER##	;ERROR IF NONE
	HRRZ	U,DDBLDB(T1)	;GET LDB ADDRESS
	JUMPE	U,RTZER##	;ERROR IF DETACHED
	LDB	T1,LDPLNO	;GET LINE NUMBER
	ADDI	T1,.UXTRM	;CONVERT TO UNIVERSAL
	JRST	STOTC1##	;SKIP RETURN INDEX TO USER
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. DISPATCH

;TRMOP. UUO, OR CALLI 116.
;UUO TO PERFORM MISCELLANEOUS FUNCTIONS FOR
;A SPECIFIED TERMINAL.
;
;CALL:	MOVE	AC,[XWD N,ADR]
;	CALLI	AC,116
;	  ERROR	RETURN
;	NORMAL	RETURN
;

TRMOP::	PUSHJ	P,SAVE4##	;SAVE THE PRESERVED AC'S
	MOVE	P4,T1		;USER'S ARGUMENT TO P4
	HRRM	T1,M		;ADDRESS OF ARGUMENT LIST
	HLRZ	T2,T1		;CHECK FOR LENGTH AT LEAST 2
	CAIL	T2,2
	PUSHJ	P,GETWRD##	;GET USER'S ARG AT M
	  JRST	TOPX3		;ERROR CODE 3, ILLEGAL ADDRESS
	TLNE	T1,-1		;IF BITS IN L.H.
	JRST	RTZER##		; THEN BAD FUNCTION
	HRRZ	P1,T1		;COPY USER ARGUMENT
	JUMPLE	P1,RTZER##	;ZERO ERROR IF BAD ARGUMENT CODE
	PUSHJ	P,GETWR1##	;GET IT, IF POSSIBLE
	  JRST	TOPX3		;NOT A LEGAL ADDRESS
	SUBI	T1,.UXTRM	;REMOVE TERMINAL OFFSET
	CAME	T1,[-1-.UXTRM]	;WANTS CONTROLLING TTY?
	JRST	TRMNRM		;NO
	HRRZ	T1,TTYTAB##(J)	;YES, GET DDB ADDRESS
	JUMPE	T1,RTZER##	;ERROR IF NONE
	HRRZ	U,DDBLDB(T1)	;GET LDB ADDRESS
	JUMPE	U,RTZER##	;DETACHED
	LDB	T1,LDPLNO	;GET LINE NUMBER
TRMNRM:	JUMPL	T1,RTZER##	;RANGE CHECK THE TERMINAL #
	CAIL	T1,TTPLEN##	;..
	  JRST	RTZER##		;BAD LINE NUMBER
	HRRZ	U,LINTAB##(T1)	;OK. GET THE LDB ADDRESS
	HRRZ	F,LDBDDB(U)	;AND DDB, IF ANY.
	JUMPN	F,TRMO1		;DID WE FIND M DDB?
	HRLZ	T2,LDBDCH(U)	;NO, GET LINE STATUS
	JUMPGE	T2,TRMO1	;PTY?
	SUBI	T1,TCONLN##+1	;YES, GET NUMBER
	HRRZ	F,PTYTAB(T1)	;GET DDB ADDR


;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

TRMO1:	MOVE	T1,P1		;GET USER'S FUNCTION CODE
	TRNE	T1,3000		;READ/SET CODE?
	JRST	TOPRSQ		;PROBABLY. GO SEE.
	CAILE	T1,TOPLN0	;IS IT AN ACTION CODE?
	JRST	RTZER##		;NO. NO SUCH CODE
	HRRI	M,1(M)		;ADVANCE M
	MOVE	P3,TOPTB0-1(T1)	;PICK UP DISPATCH WORD
IFN FTMIC,<
	MOVSI	P2,(JB.LSY)	;PROGRAM FROM SYS BIT
	TLNE	P3,(TOP.MC)	;MIC TRMOP?
	TDNN	P2,JBTLIM##(J)	;AND DID THIS PROGRAM COME FROM SYS?
	JRST	CHKRED		;NO TO EITHER
	MOVSI	P2,'MIC'	;RUNNING MIC?
	CAMN	P2,JBTNAM##(J)	;SKIP IF NO
	JRST	CHKDDB		;RUNNING MIC, NO FUTHER CHECKING REQUIRED
CHKRED:	MOVSI	T1,JP.POK
	TLNE	P3,(TOP.MR)
	PUSHJ	P,PRVBIT
	  SKIPA
	JRST	TOPX1
>
	TLNN	P3,(TOP.RP)	;DO WE NEED READ PRIVS?
	JRST	CHKWRT		;NO--SEE IF WE NEED WRITE PRIVS
	PUSHJ	P,TREDOK	;YES--DO WE HAVE READ PRIVS?
	  JRST	TOPX1		;NO--GIVE ERROR RETURN
CHKWRT:	TLNN	P3,(TOP.WP)	;DO WE NEED WRITE PRIVS?
	JRST	CHKDDB		;NO--DISPATCH
	PUSHJ	P,TWRTOK	;YES--DO WE HAVE READ PRIVS?
	  JRST	TOPX1		;NO--GIVE ERROR RETURN
CHKDDB:	TLNN	P3,(TOP.NF)	;NEED F?
	JRST	(P3)		;NO--ALLSET
	PUSHJ	P,TOPDDB	;YES--GET DDB
	  JRST	TOPX6		;CAN'T GIVE ERROR
	JRST	(P3)		;YES--DO THE TRMOP.
;HERE IF REQUESTED FUNCTION NOT FROM 1 THRU TOPLN0-1
;F AND U ARE SET UP TO THE DESIRED LINE.

TOPRSQ:	ANDI	P1,777		;JUST THE ITEM NUMBER
	TRZE	T1,1000		;READ CODE?
	JRST	TOPRED		;PROBABLY
	CAIL	T1,2000+TOPLN1	;NO. SET CODE?
	JRST	RTZER##		;NOT A LEGAL CODE
TOPSET:	HLRZ	T2,P4		;IS THERE ANOTHER DATUM?
	CAIGE	T2,3		;..
	JRST	TOPX3		;NO. CAN'T DO THE SET.
	HRRI	M,1(M)		;YES. GO GET IT
	PUSHJ	P,GETWRD##	;..
	  JRST	TOPX3		;NOT A LEGAL ADDRESS
	MOVE	P2,T1		;SAVE ARGUMENT
	PUSHJ	P,TWRTOK	;DOES HE HAVE WRITE PRIVS?
	  JRST	TOPX1		;NO. ERROR CODE 1.
TOPST1:	LDB	T1,TOPSYR	;LEGAL TO TRY SETTING.
	JUMPE	T1,TOPST2	;RANGE CHECK REQUIRED?
	HLRZ	T2,TOPSRT-1(T1)	;YES. GET MINIMUM VALUE
	CAMGE	P2,T2		;SUPPLIED .GE. MINIMUM?
	JRST	TOPX2		;NO. BAD ARG, TOO SMALL
	HRRZ	T2,TOPSRT-1(T1)	;OK. CHECK MAXIMUM
	CAMLE	P2,T2		;..
	JRST	TOPX2		;BAD. ARG TOO BIG.
TOPST2:	SKIPN	T2,TOPTB1(P1)	;SET ALLOWED?
	PJRST	RTZER##		;ILLEGAL/UNKNOWN FUNCTION
TOPST3:	TLNE	T2,(TOP.SA)	;OK TO SET?
	JRST	TOPST4		;YES--DO SO
	TLNN	T2,(TOP.PS)	;NEED PRIVS?
	JRST	TOPX1		;NO--CAN NOT SET
	MOVSI	T1,JP.POK	;POKE BIT
	PUSHJ	P,PRVBIT##	;IS IT SET?
	  JRST	TOPST4		;YES--DO SET
	JRST	TOPX1		;NO. NOT ALLOWED.
TOPST4:	TLNN	T2,(TOP.IF)	;THIS FUNCTION ILLEGAL FOR FRCLIN?
	JRST	TOPST5		;NO, CONTINUE
	LDB	T1,LDPLNO	;GET LINE NUMBER
	CAIN	T1,FRCLIN##	;IS IT FRCLIN?
	JRST	TOPX1		;YES, ILLEGAL
TOPST5:	TLNE	T2,(TOP.RT)	;NEED A ROUTINE TO SET?
	PJRST	1(T2)		;YES, SET ROUTINE IS ADDRESS+1
	LDB	T1,0(T2)	;FETCH WHAT THE STATE IS CURRENTLY
	CAMN	T1,P2		;WILL IT CHANGE?
	JRST	CPOPJ1		;NO, DON'T SEND STATUS CHANGE THEN
	MOVEI	T1,LDRPTY	;THE LINE-IS-A-PTY BIT
	CAIN	P1,4		;SET SLAVE?
	TDNN	T1,LDBDCH(U)	; ON PTY?
	DPB	P2,0(T2)	;OK. CHANGE ITEM.
IFN FTD10H,<
	CAIN	P1,27		;ARE WE SETTING APL?
	DPB	P2,[POINT 1,LDBBCD(U),11] ;YES, SET IT WHERE DLSINT
				; LOOKS FOR IT
>
TOPTFE:	MOVSI	T1,(TOP.PE)	;DO WE NEED TO CHANGE
	TDNN	T1,TOPTB1(P1)	; HARDWARE PARAMS FOR THIS LINE
	JRST	CPOPJ1##	;NO--JUST RETURN
	PUSHJ	P,SETCHP
	JRST	CPOPJ1##	;SKIP RETURN
TOPRED:	CAIL	T1,TOPLN1	;LEGAL ITEM NUMBER?
	JRST	RTZER##		;NO. ERROR RETURN
	PUSHJ	P,TREDOK	;OK TO DO A READ?
	  JRST	TOPX1		;NO. PROTECTION FAILURE.
	SKIPN	T1,TOPTB1(P1)	;OK. GET TABLE ENTRY.
	JRST	RTZER##		;ILLEGAL/UNKNOWN FUNCTION
	TLNE	T1,(TOP.RT)	;NEED A ROUTINE
	JRST	TOPRD1		;YES, GO DISPATCH
	LDB	T1,0(T1)	;GET BYTE POINTED TO
	PJRST	STOTC1##	;AND RETURN IT TO USER

TOPRD1:	PUSHJ	P,0(T1)		;ZERO OFFSET TO READ
	PJRST	STOTC1		;RETURN RESULT TO USER AND SKIP RETURN


;ROUTINE TO HANDLE FUNCTION 1000

TOPOIP:	PUSHJ	P,TOPSOP	;SKIP RETURN IF MORE TO OUTPUT
	TDZA	T1,T1		;CLEAR BUSY FLAG,OUTPUT DONE
	MOVEI	T1,1		;SET BUSY FLAG
	POPJ	P,		;RETURN
;ROUTINE TO FETCH/SET THE VALUE OF HPOS

TOPHPS:	JRST	TOPHPR		;HERE FOR READ
	LDB	T2,LDPWID	;HERE FOR SET.  GET CARRIAGE WIDTH
	MOVNS	T2		;MINUS
	ADD	T2,P2		;PLUS USERS ARGUMENT
	MOVEM	T2,LDBHPS(U)	;SETUP IN LDB
	JRST	CPOPJ1##	;AND SIGNAL GOOD RETURN

TOPHPR:	PUSHJ	P,HPOS		;GET POSITION
	MOVE	T1,T2		;GET INTO CORRECT AC
	POPJ	P,
;ROUTINE TO HANDLE FUNCTION 1041

TOPTTC:	JRST	TOPTT1		;GET TERMINAL TYPE
	MOVE	T2,P2		;GET USER'S ARGUMENT
	PUSHJ	P,TTUTYP##	;SET TERMINAL CHARACTERISTICS
	  JRST	TOPX2		;UNKNOWN TERMINAL TYPE
	JRST	CPOPJ1##	;GOOD RETURN

TOPTT1:	LDB	T1,LDPTTT	;GET TERMINAL TYPE
	TRZE	T1,100		;CUSTOMER DEFINED TERMINAL TYPE ?
	MOVNS	T1		;YES
	MOVE	T1,TTTWDT##(T1)	;GET TERMINAL NAME
	POPJ	P,		;STORE ANSWER FOR THE USER AND RETURN



;ROUTINE TO HANDLE FUNCTION 1045 (READ/SET ↑O STATE)

TOPSUP:	JRST	TOPSU5		;READ AND RETURN
	TRNE	P2,1		;SET OR CLEAR ↑O?
	JRST	TOPSU2		;SET IT
	PUSHJ	P,NOCTRO	;CLEAR IT
	JRST	CPOPJ1##	;RETURN HAPPILY

TOPSU2:	PUSHJ	P,STCTRO	;SET ↑O STATE
	JRST	CPOPJ1##	;RETURN SUCCESSFULLY

TOPSU5:	LDB	T1,LDPOSU	;GET ↑O BIT
	POPJ	P,		;AND RETURN IT TO USER



;ROUTINE TO RETURN TOTAL INPUT CHARACTER COUNT

TOPCCT:	MOVE	T1,LDBTIC(U)	;INPUT CHARACTER COUNT AVAILABLE TO USER
	ADD	T1,LDBECC(U)	;PLUS THOSE NOT YET ECHOED
	POPJ	P,		;RETURN TOTAL MONITOR CHARACTER COUNT
;SUBROUTINE TO CHECK FOR READ PRIVS
;CALL WITH:
;	F = DDB OF TARGET OR 0
;	PUSHJ	P,TREDOK
;	  RETURN HERE IF ERROR
;	RETURN HERE IF OK TO READ

TREDOK:	PUSHJ	P,SAVE3##	;SAVE P1,P2 AND P3
	MOVSI	P1,PVSPYM!PVSPYA;LOAD UP THE SPY BIT
	JRST	MYTTY		;JUMP TO COMMON CODE

;SUBROUTINE TO CHECK FOR WRITE PRIVS
;CALL WITH:
;	F = DDB OF TARGET OR 0
;	PUSHJ	P,TWRTOK
;	  RETURN HERE IF ERROR
;	RETURN HERE IF OK
;PRESERVES ALL AC'S

TWRTOK:	PUSHJ	P,SAVE3##	;SAVE P1,P2 AND P3
	MOVSI	P1,JP.POK	;FALL INTO COMMON CODE
MYTTY:	SKIPE	P2,F		;IS THERE A DDB?
	LDB	P2,PJOBN##	;YES--GET THE OWNERS JOB NUMBER
	CAMN	P2,J		;DO I OWN THIS TERMINAL
	JRST	MYTTY1		;CHECK PRIVS FOR MIC STYLE TRMOP
MYTTY2:	EXCH	P1,T1		;SAVE T1 AND SET UP PRIV BIT
	PUSHJ	P,PRVBIT##	;CHECK THE BIT
	  AOS	(P)		;OK TO READ OR SET
	MOVE	T1,P1		;RESTORE T1
	POPJ	P,0		;RETURN

MYTTY1:	
IFE FTMIC,<JRST CPOPJ1##>	;OK TO DO YOUR THING
IFN FTMIC,<
	TLNN	P3,(TOP.MC)	;MIC TRMOP?
	JRST	CPOPJ1##	;NO--OK TO DO YOUR THING
	MOVE	P2,DEVMOD(F)	;IS THE TARGET TTY...
	TLNE	P2,TTYATC	;CONTROLLING HIS JOB?
	JRST	CPOPJ1##	;YES--OK TO DO MIC TRMOP
	MOVE	P2,LDBDCH(U)	;NO--IS THE TARGET TTY...
	TRNE	P2,LDRCTY	;A CTY?
	JRST	MYTTY2		;YES--CHECK PRIVS
	CAMN	U,OPRLDB##	;IS THIS "OPR"?
	JRST	MYTTY2		;YES--CHECK PRIVS
	HRRZ	P3,TTYTAB##(J)	;GET USER'S TTY DDB ADDRESS
	JUMPE	P3,MYTTY2	;ERROR IF NONE
	HRRZ	P3,DDBLDB(P3)	;USER'S LDB ADDRESS
	JUMPE	P3,MYTTY2	;DETACHED
	MOVE	P3,LDBDCH(P3)	;USER'S TTY CHARACTERISTICS BITS
	TRNN	P3,LDRDSR	;IS HE A LOCAL TTY?
	JRST	CPOPJ1##	;YES--LET HIM DO MIC TRMOP TO EITHER REMOTE OR LOCAL TTY'S
	TRNE	P2,LDRDSR	;NO--TARGET TTY ANOTHER REMOTE TTY?
	JRST	CPOPJ1##	;YES--DO IT
	JRST	MYTTY2		;NO--CHECK PRIVS
>
;ERROR RETURNS

ERCODE	TOPX1,TRMNP%		;(1) ERROR CODE FOR PROT CHECK
ERCODE	TOPX2,TRMBR%		;(2) ERROR CODE FOR RANGE BAD
ERCODE	TOPX3,TRMIA%		;(3) ERROR CODE FOR ADDRESS BAD.
ERCODE	TOPX4,TRMCD%		;(4) ERROR CODE FOR NOT POSSIBLE TO DO
ERCODE	TOPX5,TRMDO%		;(5) ERROR IN DIALLER OPERATION
ERCODE	TOPX6,TRMND%		;(6) CAN NOT GET DDB
;TOPTB0 - TRMOP. ACTION FUNCTIONS LESS THAN 1000 

	TOP.RP==1B1		;NEED READ PRIVS TO DO THIS FUNCTION
	TOP.WP==1B2		;NEED WRITE PRIVS TO DO THIS FUNCTION
	TOP.NF==1B3		;NEED F SETUP TO DO THIS FUNCTION
IFN FTMIC,<
	TOP.MC==1B4		;THIS FUNCTION IS LEGAL IF RUNNING MIC
	TOP.MR==1B5		;FUNCTION REQUIRES MIC
>

IF2,<
IFNDEF	TOPABR,<TOPABR==RTZER##>
IFNDEF	TOPELE,<TOPELE==RTZER##>
> ;END IF2 CONDITIONAL

TOPTB0:	EXP	TOP.RP+TOPSIP			;1 - SKIP IF INPUT PRESENT
	EXP	TOP.RP+TOPSOP			;2 - SKIP IF OUTPUT PRESENT
	EXP	TOP.WP+TOPCIB			;3 - CLEAR INPUT BUFFER
	EXP	TOP.WP+TOPCOB			;4 - CLEAR OUTPUT BUFFER
	EXP	TOP.RP+TOP.WP+TOPOUC		;5 - OUTPUT CHAR
	EXP	TOP.RP+TOP.WP+TOP.NF+TOPOIC	;6 - OUTPUT IMAGE CHAR
	EXP	TOP.RP+TOP.WP+TOPOUS		;7 - OUTPUT STRING
	EXP	TOP.RP+TOP.WP+TOPINC		;10 - INPUT CHAR
	EXP	TOP.RP+TOP.WP+TOPIIC		;11 - INPUT IMAGE CHAR
	EXP	TOP.WP+TOPDSE			;12 - DATASET ENABLE
	EXP	TOP.WP+TOPDSC			;13 - DATASET CALL
	EXP	TOP.WP+TOPDSF			;14 - DATASET OFF
	EXP	TOP.RP+TOP.WP+TOPRES		;15 - RESCAN
	EXP	TOP.WP+TOPELE			;16 - SET TYPE ELEMENT
	EXP	TOP.WP+TOPABR			;17 - ENABLE AUTO BAUD DETECT
	EXP	TOP.RP+TOP.WP+TOPISC		;20 - INPUT CHAR.
	EXP	TOP.RP+TOP.WP+IFN FTMIC,<TOP.MC>+TOPMTY	;21 - MICTYP
IFN FTMIC,<
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMGT	;22 - MICGET
	EXP	TOP.RP+TOP.WP+TOP.MC+TOP.MR+TOPMST;23 - MICSET
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMCL	;24 - MICCLR
>
IFE FTMIC,<
	EXP	RTZER##				;22 - NOT IMPLEMENTED
	EXP	RTZER##				;23 - NOT IMPLEMENTED
	EXP	RTZER##				;24 - NOT IMPLEMENTED
>
	EXP	TOP.RP+TOP.WP+IFN FTMIC,<TOP.MC>+TOPMDP	;25 - MICDPY
IFN FTMIC,<
	EXP	TOP.RP+TOP.WP+TOP.MC+TOPMRS	;26 - MICDSP
IFN FTMLOG,<
	EXP	TOP.MC+TOP.RP+TOP.WP+TOPMLG	;27 - MICLOG
>
IFE FTMLOG,<
	EXP	RTZER##				;27 - NOT IMPLEMENTED
>
>
IFE FTMIC,<
	EXP	RTZER##				;26 - NOT IMPLEMEMTED
	EXP	RTZER##				;27 - NOT IMPLEMENTED
>
	EXP	TOPDSS				;30 - RETURN DATA SET STATUS
TOPLN0==.-TOPTB0
IFN FTPATT,<BLOCK 1>				;   - FOR PATCHING
;TOPTB1 - TRMOP. READ/SET FUNCTIONS GREATER THAN 1000
;CONTENTS OF TOPTB1 ARE AS FOLLOWS
;BITS 0-5 ARE RANGE TABLE INDEX FOR RANGE CHECK ON SET.
;BITS 6-12 ARE FLAGS FOR DETERMINING LEGALITY OF TRMOP UUO
;RH IS ADDRESS OF BYTE POINTER.

TOP.SA==1B6	;SET ALLOWED
TOP.PS==1B7	;SET ALLOWED FOR PRIVILEGED JOB ONLY
TOP.PE==1B8	;POKE THE FRONT END IF SET
TOP.RT==1B9	;FETCH/SET REQUIRES A ROUTINE.  ENTERED AT ADDRESS+0
		;FOR FETCH, ADDRESS+1 FOR SET.  FETCH ROUTINE MUST
		;RETURN VALUE IN T1.  SET ROUTINE'S RETURN IS PROPAGATED
		;BACK TO USER.
TOP.IF==1B10	;THIS FUNCTION IS ILLEGAL FOR FRCLIN NO MATTER IF
		;THE JOB IS PRIVILEGED OR NOT

;NOTE: THESE DEFINITIONS MUST AGREE WITH LDB DEFINITIONS
TOPTB1:	EXP	<0>B5+<TOP.RT>+<TOPOIP>					;1000
	EXP	<0>B5+<0>+<[POINT 1,LDBDCH(U),↑L<(LDLCOM)>]>		;1001
	EXP	<0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBBY2(U),↑L<L2RXON>]>;1002
	EXP	<0>B5+<TOP.SA+TOP.PE+TOP.IF>+<LDPLCT>			;1003
	EXP	<0>B5+<TOP.SA+TOP.IF>+<[POINT 1,LDBDCH(U),↑L<(LDLSLV)>]> ;1004
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPTAB>				;1005
	EXP	<0>B5+<TOP.SA>+<LDPFRM>					;1006
	EXP	<0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBDCH(U),↑L<(LDLLCP)>]>;1007
	EXP	<0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBDCH(U),↑L<(LDLNFC)>]>;1010
	EXP	<0>B5+<TOP.SA+TOP.PE+TOP.RT>+<TOPHPS>			;1011
	EXP	<1>B5+<TOP.SA+TOP.PE>+<LDPWID>				;1012
	EXP	<0>B5+<TOP.SA>+<[POINT 1,LDBBY2(U),↑L<(L2LSND)>]>	;1013
	EXP	<0>B5+<TOP.PS+TOP.IF>+<[POINT 1,LDBDCH(U),↑L<LDRHLF>]>	;1014
	EXP	<0>B5+<TOP.PS+TOP.IF>+<[POINT 1,LDBDCH(U),↑L<LDRRMT>]>	;1015
	EXP	<0>B5+<TOP.SA>+<[POINT 1,LDBPAG(U),↑L<(LPLDIS)>]>	;1016
	EXP	<2>B5+<TOP.SA+TOP.PE>+<LDPFLC>				;1017
	EXP	<0>B5+<TOP.SA+TOP.PE>+<[POINT 1,LDBBY2(U),↑L<(L2LTAP)>]>;1020
	EXP	<0>B5+<TOP.SA+TOP.PE+TOP.IF>+<[POINT 1,LDBPAG(U),↑L<(LPLPAG)>]>;1021
	EXP	<0>B5+<TOP.SA+TOP.PE+TOP.IF>+<[POINT 1,LDBDCH(U),↑L<(LDLSTP)>]>;1022
	EXP	<3>B5+<TOP.SA+TOP.IF>+<LDPPSZ>				;1023
	EXP	<3>B5+<LDPPCT>						;1024
	EXP	<0>B5+<TOP.SA>+<[POINT 1,LDBPAG(U),↑L<(LPLBLK)>]>	;1025
	EXP	<0>B5+<TOP.SA>+<LDPALT>					;1026
	EXP	<0>B5+<TOP.SA+TOP.PE+TOP.IF>+<LDPAPL>			;1027
	EXP	<4>B5+<TOP.SA+TOP.PE>+<LDPRSP>				;1030
	EXP	<4>B5+<TOP.SA+TOP.PE>+<LDPTSP>				;1031
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPDBK>				;1032
	EXP	<0>B5+<TOP.PS+TOP.PE+TOP.IF>+<LDP274>			;1033
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPTDY>				;1034
	EXP	<5>B5+<TOP.SA+TOP.PE+TOP.IF>+<LDPACR>			;1035
	EXP	TOP.SA+LDPRTC						;1036
	EXP	<0>B5+<TOP.SA>+<[POINT 36,LDBPBK(U),35]>		;1037
	EXP	<0>B5+<TOP.SA+TOP.PE>+<LDPDEM>				;1040
	EXP	<0>B5+<TOP.SA+TOP.RT+TOP.IF>+<TOPTTC>			;1041
IFN FTRSP!FTACCT,<
	EXP	<0>B5+<TOP.PS+TOP.IF>+<[POINT 36,LDBBCT(U),35]>		;1042
	EXP	<0>B5+<TOP.PS+TOP.IF>+<[POINT 36,LDBICT(U),35]>		;1043
	EXP	<0>B5+<TOP.PS+TOP.IF>+<[POINT 36,LDBOCT(U),35]>		;1044
> ;END IFN FTRSP!FTACCT
IFE FTRSP!FTACCT,<EXP 0,0,0>
	EXP	<0>B5+<TOP.SA+TOP.RT>+<TOPSUP>				;1045
	EXP	<0>B5+LDPFCS						;1046
	EXP	<0>B5+LDPBKA						;1047
	EXP	0							;1050
	EXP	0							;1051
	<0>B5+<[POINT 36,LDBTIC(U),35]>					;1052
	EXP	0							;1053
	<0>B5+<[POINT 36,LDBBKC(U),35]>					;1054
	<0>B5+<[POINT 36,LDBECC(U),35]>					;1055
	<0>B5+<TOP.RT>+<TOPCCT>						;1056
	<0>B5+<[POINT 36,LDBTOC(U),35]>					;1057
IFN FTPATT,<
	EXP	0		;FOR PATCHING
	EXP	0		;FOR PATCHING
>
TOPLN1==.-TOPTB1
TOPSYR:	POINT	6,TOPTB1(P1),5	;POINTER TO RANGE TABLE INDEX

;THIS IS THE RANGE TABLE
TOPSRT:	XWD	↑D16,↑D255	;(1)MIN AND MAX WIDTHS
	XWD	0,3		;(2)MIN AND MAX FILLER CLASSES
	XWD	0,↑D63		;(3)MIN AND MAX PAGE LENGTH
	XWD	0,17		;(4)MIN AND MAX SPEED
	XWD	0,↑D200		;(5)AUTO C.R. TABLE
IFN FTPATT,<BLOCK 1>	;FOR PATCHING
	SUBTTL	TTCALL AND TRMOP. -- SKIPS AND CLEARS

TOPSIP==SKPINC

TOPSOP::MOVSI	T2,LPLPOK	;THE TTY QUEUED-BY-TOPOKE BIT
	TDNN	T2,LDBPAG(U)	;IS THE TERMINAL QUEUED FOR SERVICE?
	SKIPL	T2,LDBDCH(U)	;NO, IS SERVICE CURRENTLY ACTIVE?
		.CREF LDLIDL	; (CREF REFERENCE TO SYMBOLIC NAME)
	JRST	CPOPJ1##	;OUTPUT ACTIVE OR TEMINAL QUEUED
	SKIPLE	LDBTOC(U)	;MORE CHARACTERS TO OUTPUT
	JRST	CPOPJ1##	;YES, SKIP RETURN
	MOVE	T2,LDBBYT(U)	;GET DEFER BITS
	TRNE	T2,L1RDEM	;IF DEFERRED ECHO,
	TRNE	T2,L1RDEC!L1RDEL ;  ONLY IF WANTS INPUT
	SKIPN	LDBECC(U)	;ANYTHING TO ECHO
	SKIPE	LDBFLP(U)	;OR OUTPUT FROM FILLERS
	AOS	0(P)		;YES. SKIP RETURN
	POPJ	P,0		;RETURN
TOPCIB:	AOS	0(P)		;SUCCESS RETURN
	PJRST	TSETBI		;CLEAR INPUT BUFFER
TOPCOB:	AOS	0(P)		;SUCCESS RETURN
	PJRST	TSETBO		;CLEAR OUTPUT BUFFER

;FOLLOWING NOT DONE YET
	TOPIIC==RTZER##

IFE FTMODM,<
	TOPDSE==CPOPJ##
	TOPDSF==CPOPJ##
	TOPDSC==CPOPJ##
	TOPDSS==CPOPJ##
>
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. I/O

;OUTPUT 1 CHAR

TOPOUC:	AOS	(P)
	PUSHJ	P,TOPDDB	;GET A DDB
	  SETZM	F		;NO--DON'T NEED IT BADLY
	JRST	ONEOUT		;TYPE

;OUTPUT A STRING

TOPMDP:	MOVEI	T1,LDROSU	;CLEAR CONTROL O BIT
	ANDCAM	T1,LDBDCH(U)	;SO DATA WILL BE SEEN
	TDZA	F,F		;SO CCTYO WILL BE USED (AVOID TIOW)
TOPOUS:	SETOM	F		;SEARCH FOR A DDB
	AOS	(P)
	PUSHJ	P,GETWDU##	;GET POINTER
	HRRZ	M,T1		;PUT IN RIGHT AC
	JUMPE	F,TOPOU1	;USE CCTYO FOR MIC TYPEOUT
	PUSHJ	P,TOPDDB	;GET DDB
	  JRST	TOPOU1		;IF NO DDB
	HRRZ	T1,TTYTAB##(J)	;CONTROLLING TTY
	CAIN	T1,(F)		;IS THIS IT?
	PJRST	OUTSTR		;YES, THEN TOPOUS IS SAME AS OUTSTR
	PUSHJ	P,SAVE4##	;SET TO JOIN OUTSTR CODE IN MIDDLE
	MOVEI	P3,TYO7W	;TYPEOUT ROUTINE
	PJRST	OUTST3		;JOIN OUTSTR

TOPOU1:	PUSHJ	P,SAVE4##	;SET TO JOIN OUTSTR CODE IN MIDDLE
	MOVEI	P3,CCTYO
	PJRST	OUTST3		;JOIN OUTSTR

;OUTPUT IMAGE CHAR

TOPOIC::AOS	(P)		;SKIP RETURN			
	JRST	IONEOU		;TYPE IT
;INPUT A CHAR

TOPISC:	SKIPA	P1,[EXP INCHRW]
TOPINC:	MOVEI	P1,INCHWL
	AOS	(P)
	LDB	T1,PUUOAC##	;WHERE TO PUT ANSWER
	HRR	M,T1
	PUSHJ	P,TOPDDB
	  SETZB	F,S		;NO DDB, NO I/O STATUS
	PUSHJ	P,TYIEAT	;EAT ANY LEFT-OVER COMMAND
	PJUMPN	F,(P1)		;INPUT AND BLOCK IF A DDB AVAILABLE
	PUSHJ	P,TYI		;NO DDB, CAN'T BLOCK, GET CHAR
	  MOVEI	T3,0		;NONE THERE--RETURN NULL
	MOVE	T1,T3		;COPY CHAR
	JRST	STOTAC##	;STORE FOR USER

;INPUT IMAGE CHAR

TOPIIC==RTZER##

;DO A RESCAN

TOPRES:	PUSHJ	P,TRESCU	;DO IT
	  JRST	CPOPJ1##	;WIN
	JRST	CPOPJ1##	;WIN
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. I/O SUBROUTINES

;GET A DDB FOR TRMOP. I/O

TOPDDB:	SETZ	S,		;IN CASE NO I/O STATUS AVAILABLE
	HRRZ	F,LDBDDB(U)	;GET DDB POINTER
	JUMPN	F,TOPDD2	;FIND A DDB?
	HRLZ	T2,LDBDCH(U)	;NO, GET THE LINE STATUS
	JUMPGE	T2,TOPDD2	;IS IT A PTY?
	LDB	T1,LDPLNO	;YES, GET THE TTY NUMBER
	HRRZ	F,PTYTAB##-PTYOFS##(T1)	;GET DDB ADDRESS, IF ANY
TOPDD2:	JUMPE	F,TOPDD1	;ANY DDB THERE?
	MOVE	S,DEVIOS(F)	;AH - A DDB, GET I/O STATUS
	LDB	T1,PJOBN##	;YES--IS IT MINE?
	CAMN	T1,.CPJOB##	; ..
	AOSA	(P)		;YES--USE IT
	SETZ	S,		;NO, THEN NO I/O STATUS AFTER ALL
	POPJ	P,		;RETURN AS APPROPRIATE

TOPDD1:	PUSHJ	P,TTYNAM	;GET SIXBIT NAME
	MOVE	T1,T2		;PUT IN T1
	PUSHJ	P,GETDDB	;GET A DDB
	  POPJ	P,		;NONE LEFT
	MOVEI	T1,ASSPRG	;INIT THE DDB SO
	IORM	T1,DEVMOD(F)	; IT WILL STICK
	MOVE	T1,.CPJOB##	; AROUND AND WE
	DPB	T1,PJOBN##	; CAN WAKE OWNER
	MOVE	S,DEVIOS(F)	;LOAD UP I/O STATUS WORD
	AOS	(P)		;SKIP RETURN (CALL?)
	PUSHJ	P,@0(P)		;CALL OUR CALLER
	  JRST	.+2		;NON-SKIP
	AOS	-1(P)		;SKIP
	PUSHJ	P,TTYREL	;KILL OFF DDB
	JRST	TPOPJ##		;AND RETURN
	SUBTTL	TTCALL AND TRMOP. -- TRMOP. DATASET FUNCTIONS

IFN FTMODM,<
;MORE SUBROUTINES FOR TRMOP

TOPDSE:	MOVE	T1,LDBDCH(U)	;GET DEVICE CHARACTERISTICS
IFN FTNET,<
	TRNE	T1,LDRREM	;REMOTE LINE
	JRST	[PUSHJ P,NETDSE	;LET NETSER DO IT
		 JRST CPOPJ1##]	;SKIP RETURN
>
	TRNN	T1,LDRDSD	;IS IT A DATASET?
	JRST	TOPX4		;NO. ERROR CODE 4
	LDB	U,LDPDSC	;GET THE TABLE OFFSET INTO U
	MOVSI	T1,DSCIC2	;CLEAR FAILURE, DIALLER FLAGS AND TIMER
	ANDCAM	T1,DSCTAB##(U)	; ..
	MOVSI	T1,DSCSWC	;SET TO ALLOW HIM ON
	PUSHJ	P,DSRRN1	;SEND TO MODEM HANDLER
	JRST	CPOPJ1##	;AND SKIP RETURN

TOPDSF:	MOVE	T1,LDBDCH(U)	;GET DEV CHARACTERISTICS
IFN FTNET,<
	TRNE	T1,LDRREM	;REMOTE LINE
	JRST	[PUSHJ P,NETDSF	;YES, LET NETSER DO IT
		 JRST CPOPJ1##]	;SKIP RETURN
>
	TRNN	T1,LDRDSD	;IS IT A MODEM
	JRST	TOPX4		;NO. CAN'T DO THIS.
	PUSHJ	P,LDBCLR	;CLEAR OUT LDB
	HRRZ	F,LDBDDB(U)	;DDB?
	JUMPE	F,TOPDF1	;NOT CONTROLLING JOB
	MOVE	T1,DEVMOD(F)
	TLNN	T1,TTYATC	;CONTROLLING TTY?
	JRST	TOPDF1		;NOPE
	PUSHJ	P,DSCDET	;DETACH IT
TOPDF1:	LDB	U,LDPDSC	;GET TABLE INDEX
	MOVSI	T1,DSCHWC	;CLEAR
	ANDCAM	T1,DSCTAB##(U)
	PUSHJ	P,DSROF1	;HANG IT UP
	JRST	CPOPJ1##	;AND SKIP RETURN

TOPDSS:	MOVE	T1,LDBDCH(U)	;CHARACTERISTICS
IFN FTNET,<
	TRNE	T1,LDRREM	;REMOTE?
	JRST	NETDSS		;YES, LET NETSER DO IT
>
	TRNN	T1,LDRDSD	;DATASET?
	JRST	TOPX4		;NO, LOSE
	LDB	U,LDPDSC	;DSCTAB OFFSET
	SKIPL	DSCTAB##(U)	;HARDWARE CARRIER?
	TDZA	T1,T1		;NO
	MOVSI	T1,DSCHWC	;YES
	JRST	STOTC1##	;STORE ANSWER FOR USER
IFE FTDIAL,<
	TOPDSC==CPOPJ##
>
IFN FTNET,<
	;CODE TO CONTROL REMOTE DATASET LINES
NETDSS:	MOVEI	T3,DSTSTS	;STATUS
	JRST	NETISR		;CALL NETSER
NETDSE:	MOVEI	T3,DSTON	;SET DATASET ON
	JRST	NETISR		;CALL NETSER
NETDSF:	MOVEI	T3,DSTOFF	;SET DATASET OFF
	JRST	NETISR		;CALL NETSER
NETDSC:	MOVEI	T3,DSTCRQ	;DIALER REQUEST
NETISR:	MOVEI	T1,ISRDSC	;DATASET CONTROL FUNCTION
	PJRST	D85DSC##	;CALL NETSER DIRECTLY SINCE NO DATASET TIMING
>
IFN FTDIAL,<
TOPDSC:
	MOVE	T1,LDBDCH(U)	;DEVICE CHARACTERISTICS
IFN FTNET,<
	TRNE	T1,LDRREM	;REMOTE LINE
	JRST	NETDSC		;YES
>
	TRNN	T1,LDRDSD	;DATASET?
	JRST	TOPX4		;NO. CAN'T DIAL THEN.
IFN FTMP,<
	PUSHJ	P,ONCPUL##	;MUST BE ON DEVICES OWN CPU
>
	LDB	U,LDPDSC	;GET DSCTAB INDEX
	MOVE	T1,DSCTAB##(U)	;AND BITS
	TLNE	T1,DSCHWC!DSCSWC	;ALREADY IN USE?
	JRST	TOPX5		;YES. CAN'T DIAL ON IT.
TOPDC1:	HRRZ	T1,DSCTAB##(U)	;GET TERMINAL NUMBER FOR MODEM
	CAME	T1,DSDUNI##	;BUSY FOR SAME UNIT, OR
	AOSN	TTYDDL##	;DIALLER FREE?
	JRST	TOPDC2		;YES
	MOVEI	T1,5		;NO. WAIT FOR IT.
	PUSHJ	P,SLEEP##	; ..
	JRST	TOPDC1		;TRY AGAIN
TOPDC2:	MOVEM	T1,DSDUNI##	;SAVE LINE BEING DIALLED
	PUSHJ	P,GETWRD##	;FROM USER CORE
	  JRST	TOPX3		;ADDRESS CHECK
	MOVEM	T1,DSCNUM	;STORE FOR DIALLER CODE
	HRRI	M,1(M)		;AND SECOND WORD
	PUSHJ	P,GETWRD##	; ..
	  JRST TOPX3		;ADDRESS CHECK
	TRO	T1,17		;GUARANTEE AN END OF NUMBER CODE
	MOVEM	T1,DSCNUM+1	;STORE SECOND WORD
	MOVSI	T1,DSCIC2	;CLEAR OUT THESE BITS
	ANDCAM	T1,DSCTAB##(U)	;IN CONTROL TABLE
	MOVSI	T1,DSCSWC!DSCDLW!↑D30
	IORM	T1,DSCTAB##(U)	;AND SET UP TO WAIT FOR DIALLER
	MOVE	T1,[POINT 4,DSCNUM]
	MOVEM	T1,TTYDDA##	;STORE INITIAL POINTER TO NUMBER
	MOVEI	T3,DSTCRQ	;CALL REQUEST CODE
	PUSHJ	P,DSCCAL	;TO THE DEVICE HANDLER
TOPDC3:	MOVEI	T1,↑D15		;SLEEP FOR FIFTEEN SECONDS
	PUSHJ	P,SLEEP##	; ..
	MOVE	T1,DSCTAB##(U)	;SEE WHAT HAPPENED.
	TLNE	T1,DSCDLF	;FAIL?
	JRST	TOPX5		;YES.
	TLNE	T1,DSCDLC	;COMPLETED OK?
	JRST	CPOPJ1##	;YES. SKIP RETURN TO USER
	JRST	TOPDC3		;NEITHER YET. LOOP.

> ;END OF FTDIAL
> ;END OF FTMODM
IFN FTCAFE!FTKS10,<

TOPABR:	MOVEI	T3,<LPCABR>B27	;SET UP FUNCTION
	MOVEI	T1,ISRLPC	;FUNCTION CODE
	SKIPGE	LDBISR(U)	;SKIP IF NOT DC76
	PUSHJ	P,@LDBISR(U)	;CALL SERVICE ROUTINE
	JRST	CPOPJ1##	;GIVE GOOD RETURN
>;IFN FTCAFE!FTKS10

;HERE TO SET TYPE ELEMENT IN 2741
IFN FT2741,<

;ASSUME THAT THE ELEMENT CAN BE SET.

TOPELE:	PUSHJ	P,GETWRD##	;GET SETTING.
	  JRST	TOPX3		;ADDRESS CHECK
	MOVE	T3,T1
	MOVEI	T1,ISRELE	;FUNCTION
	PUSHJ	P,@LDBISR(U)	;CALL ISR
	  JRST	TOPX2		;BAD NUMBER
	JRST	CPOPJ1##	;WIN
>;IFN FT2741
	SUBTTL	TTCALL AND TRMOP. -- TYPE INTO TTY ON BEHALF OF A USER

;	TOPMTY	TYPE A STRING ON BEHALF OF USER

;ADDR:	LINE NO.
;	[ASCIZ/STRING/]

TOPMTY:	PUSHJ	P,SAVE3##	;SAVE AN AC
	LDB	P1,LDPLNO	;LINE NUMBER
	PUSHJ	P,GETWRD##	;GET ADDRESS OF STRING
	  JRST	TOPX3		;ADDRESS CHECK
	HRRI	M,-1(T1)	;AND PUT IT IN M FOR FUTURE GETWD1'S
	HRROS	T1		;LEFT JUSTIFIED ASCIZ STRING
	PUSHJ	P,CKSTR##	;MAKE SURE ITS IN CORE AND LEGAL
	  JRST	TOPX3		;ADDRESS CHECK
	AOS	(P)		;GIVE GOOD RETURN

TOPMT1:	MOVE	P3,[POINT 7,P2]	;SET UP BYTE POINTER
	PUSHJ	P,GETWD1##	;GET NEXT WORD OF ASCIZ STRING
	MOVE	P2,T1		;AND SAVE IT
TOPMT2:	TLNN	P3,760000	;END OF CURRENT WORD?
	JRST	TOPMT1		;YES - GET NEXT ONE
	ILDB	T3,P3		;GET NEXT CHAR
	JUMPE	T3,PTSTRT	;END OF STRING, WAKE CONTROLLER
	MOVE	U,LINTAB##(P1)	;SET LDB ADDRESS
	PUSHJ	P,TOPTYP	;TYPE IT
	JRST	TOPMT2		;NEXT CHAR



;TOPTYP  --  TYPE ONE CHARACTER FOR USER
;CALL WITH CHARACTER IN T3, LDB IN U

TOPTYP::PUSHJ	P,PEVEN8	;COMPUTE THE PARITY
	MOVEI	T2,L1RMIF	;MIC INTERLOCK BIT
TOPMT3:	SCNOFF			;NO INTERRUPTS WHILE SETTING LOCK
	TDNE	T2,LDBBYT(U)	;CHECK INTERLOCK
	JRST	[SCNON		;ALLOW PENDING INTERRUPTS
		 JRST TOPMT3]	;TRY AGAIN
	IORM	T2,LDBBYT(U)	;SET THE INTERLOCK BIT
	SCNON			;AND ALLOW INTERRUPTS
	PUSHJ	P,RECINU	;GO AND TYPE IT
	MOVEI	T2,L1RMIF	;GET AND
	ANDCAB	T2,LDBBYT(U)	; CLEAR THE "MIC IS TYPING" FLAG
	POPJ	P,		;AND GO GET NEXT CHAR
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  SET/CLEAR LDBMIC

IFN FTMIC, <
;	MICCLR - CLEAR DOWN LDBMIC
;ADDR:	LINE NO.

;	MICSET - SET UP LDBMIC
;ADDR:	LINE NO.
;	STATUS
;
;	BOTH GIVE OLD CONTENTS OF LDBMIC IN ADDR+1

TOPMCL:	MOVEI	T1,LDRPTY	;A PTY?
	TDNE	T1,LDBDCH(U)
	PUSHJ	P,PTYOW##	;YES, TELL BATCON
	SETZ	T1,		;SET IMPLIED ZERO ARGUMENT
	JRST	TOPMS1		;JOIN MIC SET CODE

TOPMST:	PUSHJ	P,GETWRD##	;GET THE ARGUMENT
	  JRST	TOPX3		;ADDRESS CHECK
	PUSH	P,T1
	ANDI	T1,177
	CAMLE	T1,HIGHJB##	;ISOLATE JOB NUMBER
	  JRST	[POP P,T1
		 PJRST ECOD2##]	;RETURN ERROR CODE 2 (OUT OF RANGE)
	POP	P,T1
	TLZ	T1,LDLMTI!LDLMMM;CLEAR INTERNAL BITS
TOPMS1:	MOVSI	T2,LDLMIC	;GET THE MIC ACTIVE BIT
	SKIPE	T1		;...
	IORM	T2,LDBDCH(U)	; SET OR
	SKIPN	T1		;...
	ANDCAM	T2,LDBDCH(U)	; CLEAR AS NEEDED
	EXCH	T1,LDBMIC(U)	;SET NEW VALUE, RETURN OLD
	AOS	(P)		;GOOD RETURN
	PJRST	PUTWDU##	;GIVE USER OLD MIC WORD
;STILL IN IFN FTMIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  RETURN MIC STATUS

;	MICGET - GET STATUS
;ADDR:	LINE
;	RETURN RESULT TO ADDR+1

TOPMGT:	PUSHJ	P,SAVE1##	;SAVE AN AC
	SKIPN	P1,LDBMIC(U)	;IS MIC RUNNING US?
	JRST	TOPMG1		;NO FAIL RETURN
	HRRZ	F,LDBDDB(U)	;SET UP F
	JUMPE	F,TOPMG1	;ZERO MEANS HE LOGGED OUT -LOOSE HIM
	LDB	J,PJOBN##	;OTHERWISE - GET HIS JOB NO
IFN FTMP,<
	CAMN	J,COMJOB##	;ON THE SAME CPU AS US
	PUSHJ	P,ONCPU0##	;NO, GET HIM THERE
>
	PUSHJ	P,UJBSTX##	;GO GET JBTSTS
	TLZ	P1,LDLMMM!LDLMTI!LDLCL1	;CLEAR VOLATILE BITS
	TLNE	T1,(1B2)	;IN MONITOR MODE?
	TLO	P1,LDLCHK!LDLMMM;YES - SET FLAGS
IFN FTCIMP,<			;[arpa]
	SKIPE	LDBIMP(U)	;[arpa] XPATCHED?
	  PUSHJ	P,MICIMP##	;[arpa] YES, SEE IF CONNECTION CAN EAT MORE
>				;[arpa]
	TLNE	T1,(1B4)	;READY FOR I/P?
	TLO	P1,LDLCHK!LDLMTI;YES - SET FLAGS
IFN FTMLOG,<
	HRRZ	T1,LDBLOC(U)
	SKIPE	T1
	TLO	P1,LDLCHK!LDLCL1;SET TO FLAG
> ;END OF FTMLOG CONDITIONAL
	SKIPGE	LDBDDB(U)	;COMMAND WAITING?
	TLZ	P1,LDLMTI	;YES - CLEAR TI BIT
	MOVE	T1,P1		;PUT LDBMIC INTO T1 FOR
	AOS	(P)		;GOOD RETURN
	PJRST	PUTWDU##	;RETURNING TO USER

TOPMG1:	MOVSI	T1,LDLMIC	;THE CONTROLLED-BY-MIC BIT
	ANDCAM	T1,LDBDCH(U)	;CLEAR FOR XMTCHR
	SETZB	T1,LDBMIC(U)	;CLEAR DOWN LDBMIC
	PJRST	PUTWDU##	;AND EXIT
;STILL IN IFN FTMIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  READ ERROR RESPONSE TEXT

;	MICRSP : RECORD ERROR MESSAGE
;ADDR:	LINE NO.
;	ADDRESS OF SPACE TO RETRIEVE RESPONSE

TOPMRS:	SKIPE	T2,LDBMIC(U)	;RUNNING MIC
	TLNN	T2,LDLERC	;ERROR?
	JRST	TOPX4		;NO
	TLNN	T2,LDLRSY	;MAKE SURE GOT TO INT LEVEL WITH SYNC
	JRST	TOPX4		;NO

	PUSHJ	P,GETWRD##	;GET ADDRESS OF RESPONSE BUFFER
	  JRST	TOPX3		;ADDRESS CHECK
	PUSHJ	P,MICADC
	  JRST	TOPX3		;ADDRESS CHECK OF BUFFER
	PUSHJ	P,SAVE3##	;SAVE WORKING ACS
	MOVSI	P1,(<POINT 7,>)
	ADDI	P1,(T1)
	MOVEI	P2,<21*5>-1	;MAX SPACE IN BUFFER
	CAMLE	P2,LDBTOC(U)	;GOT THIS MANY?
	MOVE	P2,LDBTOC(U)	;NO - USE LESSER
	JUMPLE	P2,TOPX4	;NO CHARACTERS
	SKIPN	P3,LDBTOT(U)	;GET CHAR ADDRESS OF ERROR LINE
	JRST	TOPX4		;HASN'T GOT ONE?

TOPMR1:	LDCHK	T3,P3		;GET NEXT CHARACTER
TOPMR2:	EXCTUU	<IDPB T3,P1>
	JUMPE	T3,TOPMR3	;EXIT HAVING MADE ASCIZ
	SOJG	P2,TOPMR1	;GET NEXT CHAR
	SETZ	T3,		;MAKE ASCIZ
	JRST	TOPMR2

TOPMR3:	MOVSI	T1,LDLRSP!LDLRSY;CLEAR RESPONSE FLAG
	ANDCAM	T1,LDBMIC(U)
	AOS	(P)		;GOOD RETURN TO THE USER
	PJRST	TOPOKE		;START UP TERMINAL OUTPUT - GOOD EXIT
;STILL IN IFN FTMIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  LOG ALL TERMINAL OUTPUT

IFN FTMLOG,<

;	MICLOG: RECORD ALL UUO LEVEL OUTPUT
;ADDR:	LINE NUMBER
;	ADDR LOG BUFFER

TOPMLG:	SKIPE	T2,LDBMIC(U)	;RUNNING MIC?
	TLNN	T2,LDLLOG	;WANT LOG FEATURE?
	JRST	TOPX4

	PUSHJ	P,GETWRD##
	  JRST	TOPX3		;ADDRESS CHECK
	PUSHJ	P,MICADC	;ADDRRESS CHECK ALL OF BUFFER
	  JRST	TOPX3		;ADDRESS CHECK
	AOS	(P)		;SET FOR GOOD RETURN TO THE USER
	PUSHJ	P,SAVE2##	;SAVE WORKING ACS
	MOVSI	P1,440700
	HRRI	P1,(T1)
	MOVEI	P2,<21*5>-1

TOPML1:	SCNOFF			;DOWN PI SYSTEM
	SOSGE	LDBLOC(U)	;CHECK COUNT
	JRST	[SETZB T3,LDBLOC(U) ;FIX COUNT
		 JRST TOPML3]	;JOIN PROCESSING
	LDCHKR	T3,LDBLOT(U)	;TAKE A BYTE
TOPML3:	SCNON			;TURN PI'S BACK ON
TOPML2:	EXCTUU	<IDPB T3,P1>
	JUMPE	T3,XMTWAK
	SOJG	P2,TOPML1
	SETZ	T3,
	JRST	TOPML2		;LOOP UNTIL COUNT EXHAUSTED OR END BUFFER
> ;END OF FTMLOG CONDITIONAL
;STILL IN IFN FTMIC
	SUBTTL	TTCALL AND TRMOP.  --  MIC  --  MISCELLANEOUS MIC SUBROUTINES

IFN FTMLOG,<

; HERE WITH SCANNER INTERRUPTS DISABLED

MICLGC:	MOVE	T1,LDBMIC(U)	;GET MIC STATUS
	TLNN	T1,LDLLOG	;LOGGING?
	JRST	MICLG1		;NO-MIC HAS GIVEN UP MUST TIDY

	MOVE	T1,LDBTOP(U)	;MOVE TAKER TO PUTTER
	MOVEM	T1,LDBTOT(U)	;SO MIC CAN CATCH UP WITH PUTPUT
	MOVE	T1,LDBTOC(U)	;REMEMBER HOW MANY
	ADDM	T1,LDBLOC(U)	;KEEP TRACK FOR MIC
	JRST	MICLG2
;MIC HAS GONE AWAY MUST TIDY UP LOG BUFFER

MICLG1:	MOVE	T1,LDBLOT(U)	;MOVE PUTTER AND TAKER
	MOVEM	T1,LDBTOT(U)
	MOVEM	T1,LDBTOP(U)	;BACK UP
	SETZM	LDBLOT(U)	;ZAP LOG BUFFER
MICLG2:	SETZM	LDBTOC(U)	;ZAP COUNT
	JRST	SONPPJ		;AND EXIT
> ;END OF FTMLOG CONDITIONAL
;STILL IN IFN FTMIC

;SUBROUTINE TO ADDRESS CHECK A USER BUFFER

MICADC:	PUSH	P,M
	PUSH	P,T1
	HRRI	M,(T1)
	PUSHJ	P,GETWRD##
	  JRST	MICAD1
	HRRI	M,21(M)
	PUSHJ	P,GETWRD##
	TRNA
	AOS	-2(P)
MICAD1:	POP	P,T1
	JRST	MPOPJ##
;STILL FTMIC

;SUBROUTINE TO SET UP HORIZONTAL POSITION FOR MIC AND TO CHECK FOR
;OPERATOR AND ERROR CHARS IN COLUMN 1

MICPOS:	SKIPN	T2,LDBMIC(U)	;MIC RUNNING FOR THIS LINE?
	POPJ	P,		;NO, RETURN IMMEDIATELY
	PUSH	P,T3		;PRESERVE CHAR
	ANDI	T3,177		;MASK OFF PARITY
	PUSHJ	P,SPCHEK	;GET CHARACTERISTICS OF CHAR
	  JRST	MICPS2		;NOT SPECIAL
	TLNN	T1,CHCRET	;IS IT <CR>?
	JRST	MICPS1		;NOT - MUST CHECK OTHERS
	TLO	T2,LDLCL1	;SET COL 1 FLAG IN MICLDB
	MOVEM	T2,LDBMIC(U)
	JRST	T3POPJ##	;AND RETURN

MICPS1:	CAIE	T3,177		;IS IT A RUBOUT
	CAIN	T3,12		;OR LINE-FEED
	JRST	T3POPJ##	;YES - NO CHECKING
MICPS2:	TLZN	T2,LDLCL1	;ARE WE IN COLUMN 1?
	JRST	T3POPJ##	;NO - RETURN
	LDB	T1,LDP.OP	;GET OPERATOR CHAR
	JUMPE	T1,MICPS4	;JUMP IF NOT SET
	CAMN	T1,T3		;HAVE WE FOUND ONE?
	TLO	T2,LDLCHK!LDLOPC;YES - SET BITS
MICPS4:	LDB	T1,LDP.ER	;GET ERROR CHAR
	JUMPE	T1,MICPS3	;IF NO ERROR
	CAIE	T3,"?"		;"?" ERROR CHARACTER
	CAMN	T1,T3		;ONE OF THOSE?
	TLO	T2,LDLCHK!LDLERC;YES - SET ITS FLAGS
MICPS3:	MOVEM	T2,LDBMIC(U)	;STORE MIC WORD
	JRST	T3POPJ##	;RESTORE T3, AND RETURN
;STILL IN IFN FTMIC



;STILL FTMIC

IFN FTMLOG,<
;A ROUTINE TO FREE THE MIC LOG BUFFER IF REQUIRED

MLOGOF:	SKIPN	LDBLOT(U)	;HAS NOT GOT ONE
	POPJ	P,0
	SCNOFF			;SNEAKY PEEK
	SKIPE	LDBTOC(U)	;OUTPUT BUFFER IDLE
	JRST	SONPPJ		;NO FORGET IT
	JRST	MICLG1		;YES-GO ZAP LOG BUFFER AND TURN ON PI
> ;END OF FTMLOG CONDITIONAL

;ROUTINE TO WAKE MIC UP WHEN CONTROLLED JOB REQUIRES INPUT
MICWAK:	LDB	T1,LDPMJN	;LOAD MASTER JOB NO.
	CAMLE	T1,HIGHJB##	;JOB NUMBER TOO BIG?
	  JRST	MICWA1		;YES JUST RETURN
	MOVE	T2,JBTSTS##(T1)	;CHECK JOB STATUS
	TLNN	T2,JLOG		;LOGGED IN?
	  JRST	MICWA1		;NO JUST RETURN
	PUSHJ	P,WAKJOB##	;GO WAKE MIC
MICWA1:	MOVE	T1,LDBDCH(U)	;RESTORE C(U)
	POPJ	P,		;AND RETURN

MICECH:	TLNN	T1,CHCRET	;IS IT A <CR>?
	POPJ	P,		;NO, RETURN
	PUSH	P,T1		;SAVE T1
	MOVSI	T1,LDLCL1	;YES, SET COL 1 BIT
	IORM	T1,LDBMIC(U)	; IN LDBMIC
	JRST	TPOPJ##		;RETURN

MICRIC:	CONSO	PI,PI.IPA	;AT INTERRUPT LEVEL?
	POPJ	P,		;NO, THEN MIC TYPED IT
MICPRC:	CAIE	T3,1		;IS THE CHAR A ↑A
	CAIN	T3,201		;WITH POSSIBLE PARITY?
	JRST	MICRIA		;YES - GO DEAL WITH ↑A
	TLO	T1,LDLCHK!LDLMCC;SAY THAT ↑C WAS TYPED
	MOVEM	T1,LDBMIC(U)	;PUT IT BACK
	POPJ	P,		;AND RETURN
;STILL FTMIC

MICRIA:	TLO	T1,LDLCHK!LDLMCA;SAY ↑A
	MOVEM	T1,LDBMIC(U)	;PUT IT AWAY!
	TRC	T3,202		;CONVERT CHAR INTO A ↑C
	MOVSI	T1,CHBRK!CHCRE!CHCNC
	IORM	T1,-1(P)	;AND SET UP BITS TO LOOK LIKE ↑C
	POPJ	P,

PTYMCK:	CAIN	T3,20
	TLO	T2,LDLCHK!LDLMCP
	CAIN	T3,2
	TLO	T2,LDLCHK!LDLMCB
	MOVEM	T2,LDBMIC(U)
	TLNE	T2,LDLMCP!LDLMCB
	JRST	RICB3
	JRST	PTYPT1
> ;END IFN FTMIC

;CO-ROUTINE TO SETUP U AND .CPTOA SO THAT THE MONITOR CAN TYPE
; A COMMAND AT ITSELF.  USES LDB CORRESPONDING TO FRCLIN

FRCSET::EXCH	U,(P)		;GET CALLER'S PC, SAVE U
	PUSH	P,.CPTOA##	;SAVE .CPTOA
	MOVEM	U,1(P)		;WHERE TO RETURN TO CALLER
	MOVEI	U,TOPTYP	;PUT CHARS INTO INPUT
	MOVEM	U,.CPTOA##	; STREAM
	MOVE	U,LINTAB##+FRCLIN## ;LDB
	PUSHJ	P,@1(P)		;CALL CALLER AS A SUBROUTINE
	  CAIA			;NON-SKIP
	AOS	-2(P)		;PROPAGATE SKIP
	POP	P,.CPTOA##	;RESTORE .CPTOA
	JRST	UPOPJ##		;RESTORE U AND RETURN
	SUBTTL	SUBROUTINES FOR I/O

;SUBROUTINE TO READ A CHARACTER AND KEEP THE BREAK COUNT RIGHT
;
;IT IS ASSUMED THAT THE CALLER HAS DONE ANY NECESSARY WAITING. THERE
;ARE TWO UNUSUAL CASES: FIRST, IF THERE ARE NO CHARACTERS IN THE
;BUFFER, TYI WILL NON-SKIP RETURN. IF THE CHARACTER READ IS A
;CONTROL C, AND IF THE TERMINAL IS IN USER MODE, NOT SLAVED, NOT
;IN IMAGE INPUT STATE, AND NOT RUNNING UNDER JACCT, THEN TYI CALLS
;ROUTINES TO PUT CONSOLE AT MONITOR LEVEL, AND GOES BACK INTO I/O
;WAIT UNTIL A POSSIBLE CONTINUE COMMAND.
;
;IT IS THE CALLER'S RESPONSIBILITY TO EAT ANY POSSIBLE COMMAND LEFT
;LYING AROUND (I.E., CALL TYIEAT).
;
;TYICC USES P3! BE WARNED!

TYIS:	PUSHJ	P,SAVE3##	;REALLY SHOULD DO IT
	SETOM	P3		;FLAG DON'T WAIT IF NOTHING THERE
	JRST	TYICC2

TYI:	PUSHJ	P,SAVE3##
	TDZA	P3,P3		;FLAG WAIT ON ↑C, CONTINUE
TYICC:	TDZA	P3,P3		;FLAG WAIT ON ↑C, CONTINUE SEQUENCE
TYICC2:	SETZB	P1,P2		;INDICATE NO BUFFER
TYICC3:	TRNE	S,IODERR	;HAS HE GOTTEN A ↑C?
	POPJ	P,		;YES, FORGET IT
TYICC4:	SCNOFF			;NO RACES
	SOSGE	LDBTIC(U)	;ANY LEFT TO INPUT?
	JRST	TYICCZ		;FIX INPUT COUNT AND RESTORE PI
	LDCHKR	T3,LDBTIT(U)	;GET CHARACTER
	MOVE	T2,LDBTIT(U)	;INPUT TAKER POINTER
	CAMN	T2,LDBBKU(U)	;TAKEN LAST BREAK?
	SETZM	LDBBKU(U)	;YES, ZAP POINTER TO IT
	SCNON			;ALLOW INTERRUPTS
	PUSH	P,T3		;PRESERVE CHAR.
	SKIPG	LDBTIC(U)	;IS THIS THE LAST CHARACTER IN THE BUFFER
	PUSHJ	P,CHKXON	;YES, GO CHECK IF XON IS NEEDED
	POP	P,T3		;RESTORE CHAR.
	TRNE	T3,400		;IMAGE CHARACTER?
	JRST	CPOPJ1##	;YES, DONE HERE

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

TYIC:
IFN FTCIMP,<			;[arpa]
	SKIPN	LDBIMP(U)	;[arpa] NO FURTHER PROCESSING IF XPATCHED
>				;[arpa]
	PUSHJ	P,SPCHEK	;SEE WHAT KIND OF CHARACTER IT IS
	  JRST	CPOPJ1##	;NOTHING SPECIAL
	JUMPE	T3,TYICC4	;IF NULL, SKIP IT.
	TLNE	T1,CHALT	;SOME ALT CHAR?
	TLNE	U,LDLFCS	;FULL CHR SET?
	CAIA			;NO CONVERSION
	PUSHJ	P,RIALTO	;CONVERT
	TLNE	T1,CHBRK	;BREAK CHARACTER?
	SOS	LDBBKC(U)	;YES. COUNT IT DOWN.
	JUMPE	F,CPOPJ1##	;GOOD RETURN IF NO DDB
	TLNN	T1,CHCNC	;CONTROL C CHARACTER?
	JRST	CPOPJ1##	;NO JUST RETURN TO CALLER
	MOVE	T1,DEVMOD(F)	;GET SOME BITS
	TLNN	T1,TTYATC	;IS TTY CONTROLLING A JOB?
	JRST	CPOPJ1##	;NO, RETURN CHAR
	HLL	U,LDBDCH(U)	;GET LINE STATE FLAGS
	PUSHJ	P,CNCCHK	;SEE IF IT IS A CONTROL C
	  JFCL			;YES, STORE
	  JRST	CPOPJ1##	;YES, BUT IT SHOULD BE STORED.
	MOVE	S,[XWD	IOW,IOACT]
	IORB	S,DEVIOS(F)
	SKIPN	P3		;WAIT?
	PUSHJ	P,TIWAIT	;NOW WAIT IN CASE TYPE CONTINUE
	PUSHJ	P,TYIEAT	;EAT THE CONTINUE COMMAND
	JUMPE	P1,TYICC3	;DONE IF NO PTR
	DMOVE	T1,P1		;SETUP BYTE POINTER AND COUNT SO PRNGE CAN
	PUSHJ	P,PRNGE##	;MAKE SURE BUFFER DIDN'T GO AWAY
				; (USER TYPED .CORE <SMALLER-VALUE> AND
				;  ZAPPED THE END OF HIS BUFFER)
	JRST	TYICC3		;LOOP AROUND AGAIN.


;HERE WITH THE PI SYSTEM TURNED OFF AFTER INPUT COUNT HAS BEEN
;FOUND EXHAUSTED.  (PROBABLY BY A SOSGE THAT DID NOT SKIP).

TYICCZ:	SETZM	LDBTIC(U)	;FIX CHARACTER COUNT
	SETZM	LDBBKU(U)	;CLEAR BREAK POSITION
	SETZM	LDBBKC(U)	; AND COUNT, SINCE EMPTY
	JRST	SONPPJ		;RESTORE PI AND NON-SKIP RETURN
;SUBROUTINE TO DISCARD A COMMAND FROM INPUT BUFFER IF L2RECS STILL ON

TYIEAT:	MOVEI	T1,L2RECS	;GET EAT CHARACTER SYNC BIT
	TDNN	T1,LDBBY2(U)	;STILL WANT COMMAND EATEN?
	POPJ	P,0		;NO. RETURN.
TYIL:	SCNOFF			;NO RACES
	SOSGE	LDBTIC(U)	;ANY CHARACTERS LEFT?
	JRST	[SETZM	LDBTIC(U)	;FIX COUNT
		SCNON		;LET WORLD BACK IN
		JRST	TYID]	; AND GIVE UP
	LDCHKR	T3,LDBTIT(U)	;TAKE A CHARACTER
	MOVE	T2,LDBTIT(U)
	CAMN	T2,LDBBKU(U)	;TAKEN LAST BREAK?
	SETZM	LDBBKU(U)	;ZAP POINTER
	SCNON			;ALLOW INTERRUPTS
	PUSHJ	P,SPCHEK	;GET CHARACTER DESCRIPTORS
	  JRST TYIL		;ORDINARY
	TLNE	T1,CHBRK	;BREAK CHAR?
	SOSA	LDBBKC(U)	;YES. COUNT IT AND QUIT
	JUMPN	T3,TYIL		;NO. LOOP IF STILL SOME TO GO
TYID:	MOVEI	T1,L2RECS	;NOW CLEAR THE BIT
	ANDCAM	T1,LDBBY2(U)	;IN THE DEVICE WORD
	POPJ	P,0
;HERE ARE THE ROUTINES TO PERFROM VARIOUS "TTY INPUT" FUNCTIONS

CTIGNC::PUSHJ	P,CTICOM	;GET THE NEXT CHARACTER (IN T3)
CTIGLC::PUSHJ	P,CTICOM	;GET THE "LAST CHAR COMCON READ" (IN T3)
CTISLC::PUSHJ	P,CTICOM	;SET THE "LAST CHAR" (FROM T3)
CTIGBP::PUSHJ	P,CTICOM	;GET THE BYTE POINTER BEING USED (IN T1)
CTISBP::PUSHJ	P,CTICOM	;SET THE BYTE POINTER TO USE (FROM T1)

CTICOM:	EXCH	T4,(P)		;SAVE "T4" GET OFFSET
	ANDI	T4,-1		;GET JUST THE ADDRESS
	SUBI	T4,CTIGNC+1	;MAKE IT 0 ORIGIONED
	ADD	T4,.CPTIV##	;GET ADDRESS OF TTY INPUT VECTOR TO USE
	XCT	(T4)		;CALL EITHER COMCON OR ONCE
	POP	P,T4		;RESTORE T4
	POPJ	P,		;  AND RETURN

;HERE IS THE "NORMAL" TTY INPUT VECTOR
COMTIV::PUSHJ	P,CCTYI		;CCTYI GET'S NEXT CHAR
	LDB	T3,LDPLCH	;LAST CHAR IS HERE
	DPB	T3,LDPLCH	; STILL HERE...
	MOVE	T1,LDBCLP(U)	;BYTE POINTER IS HERE
	MOVEM	T1,LDBCLP(U)	; STILL HERE...

;ROUTINE TO "GET NEXT CHAR" FROM NORMAL LINES
CCTYI::	SCNOFF			;NO RACES
	SKIPE	T2,LDBCLP(U)	;ADDRESS THERE TO USE?
	CAMN	T2,LDBTIP(U)	;YES. CAUGHT UP TO PUTTER?
	JRST	CCTYI1		;YES.  RETURN END OF LINE CHARACTER
	LDCHK	T3,LDBCLP(U)	;LOAD CHARACTER FROM TTCMCA POINTER
	JRST	SONPPJ		;ALLOW INTERRUPTS AND RETURN

CCTYI1:	MOVEI	T3,12		;RETURN BREAK CHAR
	JRST	SONPPJ
;SUBROUTINE TO SEE IF A CONTROL C SHOULD BE ACTED ON OR STORED.
;NON-SKIP MEANS STORE IT.
;SKIP MEANS JACCT SET
;DOUBLE SKIP MEANS .HALT DONE.

CNCCHK:	TLNE	U,LDLSLV+LDLIMI	;SHOULD ↑C BE RETURNED?
	POPJ	P,0		;YES.
	AOS	(P)		;ADVANCE RETURN
	PUSH	P,T1		;MAYBE NOT. SAVE T1.
	HRRZ	F,LDBDDB(U)	;GET LINE'S JOB
	JUMPE	F,CNCCK1	;IF NO DDB ATTACHED, ASSUME SHOULD DO ↑C
	LDB	T1,PJOBN##	; ..
	MOVE	T1,JBTSTS##(T1)	;GET JOB STATUS WORD
	TDNE	T1,[XWD JACCT,JS.DEP]	;IS ↑C LEGAL? (PRIVILEGED PROG OR
				; DAEMON ERROR PAUSE)
	JRST	TPOPJ##		;NO. GIVE IT TO CUSP

	PUSHJ	P,CNCMOD
CNCCK1:	PUSHJ	P,TTHALT	;FORCE CONTROL C
	JRST	TPOPJ1##	;RESTORE T1, SKIP RETURN

CLRIIQ:	HRRZ	F,LDBDDB(U)	;GET DDB, IF ANY.
	JUMPE	F,CLRIM1	;CLEAR BIT IF NO DDB
	MOVE	S,DEVIOS(F)	;GET STATUS WORD.
	TRNE	S,I		;IF STILL IMAGE, DON'T CLEAR BIT
	POPJ	P,0		;IMAGE. JUST RETURN
CLRIMI:	HRRZ	F,LDBDDB(U)	;GET ATTACHED JOB, IF ANY
	JUMPE	F,CLRIM1	;IF NONE, SKIP PART OF THIS
	MOVSI	S,FRCEND	;ALSO CLEAR FORCED END OF FILE BIT
	ANDCAB	S,DEVIOS(F)
CLRIM1:	MOVSI	T1,LDLIMI	;NO. CLEAR IMAGE BIT AND TIME
	DPB	T1,LDPTIM	; ..
	ANDCAM	T1,LDBDCH(U)	; ..
	PJRST	SETCHP		;TELL THE FRONT END AND RETURN
;ROUTINE TO PUT TERMINAL INTO MONITOR COMMAND MODE. DON'T CALL THIS
;ROUTINE IF TERMINAL IS A SLAVE, UNLESS YOU WANT SLAVE BIT CLEARED TOO.
;CALL WITH LINE SET.

CNCMOD::
IFN FTTVP,<PUSHJ P,CLRPCT>	;CLEAR PAGE COUNTER
	PUSHJ	P,STRTDL	;LET ONE DEFERRED LINE ECHO
	MOVEI	T1,L2RECS	;EAT RACE SYNC BIT
	ANDCAM	T1,LDBBY2(U)
	HRRZ	T1,LDBDDB(U)	;DDB ADDRESS
	JUMPE	T1,CNCMO2	;IF NO DDB, DON'T TRY TO TOUCH IT
	MOVEI	T2,PIMMOD	;MAKE SURE THAT PIMMOD
	ANDCAM	T2,DEVIOS(T1)	;ISN'T SET IN THE DDB
	MOVSI	T2,LDLBKA	;THE VOLATILE BREAK-ON-ALL-CHARACTERS BIT
	TDNN	T2,LDBDCH(U)	;IN CHARACTER MODE?
	TDZA	T2,T2		;NO
	MOVSI	T2,IOLBKA	;YES, REMEMBER THAT FACT
	IORM	T2,DEVIOS(T1)	;FOR TTYUSR TO FIND LATER
CNCMO2:	MOVE	T1,[LDLIMI+LDLNEC+LDLDLR+LDLBKA+LDLPIM,,LDROSU]
	ANDCAM	T1,LDBDCH(U)	;CLEAR ALL THESE BITS
	MOVSI	T1,LDLCOM	;AND SET THIS ONE
	IORB	T1,LDBDCH(U)	; ..
	TRNE	T1,LDRPTY	;IS THIS LINE PTY-DRIVEN?
	PUSHJ	P,PTMNMD##	;YES. TELL PTYSER ABOUT IT.
	PUSHJ	P,SETCHP	;BE SURE REMOTES ARE INFORMED
	PJRST	NOCTRO		;CLEAR ↑O AND RETURN


;SUBROUTINE TO SKIP IF TERMINAL IS AT COMMAND LEVEL AND NOT SLAVED

COMQ:	SKIPGE	LDBDDB(U)	;LDBCMR ON?
	JRST	CPOPJ1##	;YES. ASSUME COMMAND LEVEL
	HLL	U,LDBDCH(U)	;GET LINE STATE
	TLNE	U,LDLCOM	;AT TOP LEVEL?
	TLNE	U,LDLSLV	;AND NOT SLAVED?
	POPJ	P,0		;NO. JUST RETURN
	HRRZ	F,LDBDDB(U)	;IS LINE ATTACHED TO A JOB?
	JUMPE	F,CPOPJ1##	;JUMP IF NOT
	PUSH	P,T1		;SAVE AN AC
	MOVE	T1,DEVMOD(F)	;GET DEVICE ASSIGN BITS
	TLNE	T1,TTYATC	;ATTACHED TO JOB?
	JRST	TPOPJ1##	;YES. SKIP RETURN
	LDB	T1,PJOBN##	;IS JOB NUMBER ZERO?
	JUMPE	T1,TPOPJ1##	;IF SO,SKIP RETURN
	JRST	TPOPJ##		;IF NOT ATTACHED, CAN'T DO COMMAND
;ROUTINE TO MAKE THIS TERMINAL VISIBLE TO COMMAND DECODER, IF AT COM LEVEL
;CALL WITH LINE SET UP

COMSET::PUSHJ	P,COMQ		;IS LINE AT COMMAND LEVEL?
	  POPJ	P,0		;NO. JUST RETURN
IFN	FTTVP,<PUSHJ P,CLRPCT>	;CLEAR PAGE COUNTER
	MOVSI	T1,LDBCMR	;OK. SET REQUEST BIT
COMST1:	SCNOFF			;CAN'T LOOK AT LDBDDB(U) HERE
COMSTF::SKIPL	LDBDDB(U)	;WAS COMMAND REQUEST ON?
	AOS	COMCNT##	;NO. WAKE COMCON
	IORM	T1,LDBDDB(U)	;SET THE BITS IN LDBDDB(U)
	SCNON			;FALL INTO CMDSET

;SUBROUTINE TO SET/CLEAR BIT IN COMMAND MAP

CMDSET::SKIPA	T1,[IORM T3,CMDMAP##(T2)]
CMDCLR::MOVE	T1,[ANDCAM T3,CMDMAP##(T2)]
	PUSH	P,T3		;SAVE T3
	SETZM	T3
	LDB	T2,LDPLNO	;GET LINE #
	LSHC	T2,-5		;SET TO WORD ADDRESS
	ROT	T3,5		;BIT WITHIN WORD
	MOVE	T3,BITTBL##(T3)	;GET THE BIT
	XCT	T1		;SET OR CLEAR
	PJRST	T3POPJ##	;RETURN
TTFCOM::				;FORCED COMMAND TABLE
PHASE 0
TTFCXC:!SIXBIT /.HALT/			;CONTROL C
IFN FTMODM!FtCImp,<			;[arpa] needed for arpanet, too.
TTFCXD::!SIXBIT /.BYE/			;DATAPHONE DISCONNECT
TTFCXH::!SIXBIT /.HELLO/		;DATAPHONE CONNECT
>
TTFCXR::!SIXBIT /.RESTA/		;SYSTEM RESTART
TTFCXK:!SIXBIT /KJOB/			;FORCED KILL JOB
TTFCXI::!SIXBIT /INITIA/		;INITIALIZING CUSP CALL

IFN FTJCON,<
TTFCXJ::!SIXBIT /.FCONT/		;FORCED CONTINUE
>
IFN FTDAEM,<
TTFCXU::!SIXBIT /.DUMP/			;CCL RUN OF DUMP
>
TTFCXT:!SIXBIT	/.TYPE/			;RETYPE LINE
IFN FTWATCH,<
TTFCXW:!SIXBIT	/USESTA/		;1 LINE SYSTAT
>
IFN FTNET,<
TTFCXL::!SIXBIT	/.NETLD/		;AUTO DOWN LINE LOAD OF DAS80'S SERIES.
>
TTFCXS:!SIXBIT	/HALT/			;STOP JOB REGARDLESS OF ↑C TRAPPING

IFN FTCIMP,<				;[arpa]
TTFCXF::!SIXBIT	/.FTPSV/		;[arpa] run the FTP SERVER
TTFCXG::!SIXBIT	/FINGER/		;[arpa] SUPPORT A FINGER SERVER
>					;[arpa]


IFN FTPATT,<
TTFCXX:!SIXBIT /CTEST/			;FOR PATCHING
>
DEPHASE
TTFCML==:.-TTFCOM
MTTFCM==:-TTFCML				;MINUS LENGTH OF FORCED COMMAND TABLE
IFG TTFCML -20,<PRINTX ?TOO MANY FORCED COMMANDS!>
	SUBTTL	COMMAND LEVEL ROUTINES

;ROUTINE TO SET UP TO READ A COMMAND FROM ANY REQUESTING LINE
;CALL FROM CLOCK LEVEL:
;	PUSHJ P,TTYCOM
;	  NONE FOUND
;	FOUND ONE	;F, U SET UP. J HAS JOB # IF ANY,
;			;T2 HAS TYPEIN T2

TTYCOM::MOVE	T1,BITTBL##+<FRCLIN##-<FRCLIN##/↑D32>*↑D32>
	TDNN	T1,CMDMAP##+<FRCLIN##/↑D32>
	SKIPA	T1,LINSAV##
	MOVEI	T1,FRCLIN##	;DO SYSTEM COMMANDS FIRST
	MOVEM	T1,LINSAV##
	CAIL	T1,TTPLEN##	;GREATER THAN HIGHEST LINE #?
TTYCM0:	SETZB	T1,LINSAV##	;YES, START AT LINE 0
	LSH	T1,-5		;SHIFT TO RIGHT PLACE
	HRLI	T1,TTCMPT##(T1)	;FORM AN AOBJN POINTER
TTYCM1:	SKIPE	T2,CMDMAP##(T1)	;GET A WORD OF BITS
TTYCM2:	JFFO	T2,TTYCM3	;FIND FIRST ONE BIT
	AOBJN	T1,TTYCM1	;LOOP TO TOP OF TABLE
	SKIPE	LINSAV##	;LOOKED AT THE ENTIRE TABLE?
	JRST	TTYCM0		;NO, START AT THE BEGINNING
	POPJ	P,0		;GIVE FAIL RETURN
TTYCM3:	MOVEI	T4,(T1)		;COPY WORD #
	LSH	T4,5		;SHIFT TO RIGHT PLACE
	ADDI	T4,(T3)		;ADD IN BIT NUMBER
	CAML	T4,LINSAV##	;SKIP IF LINE IS TOO SMALL
	JRST	TTYCM4		;ELSE FIX # AND PROCESS
	TDZ	T2,BITTBL##(T3)	;CLEAR BIT
	JRST	TTYCM2		;AND TRY NEXT
TTYCM4:	MOVEM	T4,LINSAV##	;SAVE THIS LINE #
	AOS	(P)		;GIVE SKIP RETURN
TTCM4A:	HRRZ	U,LINTAB##(T4)	;PICK UP LDB POINTER
TRESCN::HRRZ	F,LDBDDB(U)	;GET DDB ADDRESS IF ANY
	JUMPE	F,TRESC1	;JUMP IF NO DDB
	MOVE	T3,DEVMOD(F)
	TLNN	T3,TTYATC
TRESC1:	TDZA	J,J
	LDB	J,PJOBN##
IFN FTNET,<			;NETWORK AUTO-DISCONNECT FEATURE
	SETZ	T2,		;GET A ZERO FOR THE TIMER
	MOVE	T3,LDBDCH(U)	;GET THE DEVICE CHARACTERISTICS
	TRNE	T3,LDRREM	;IS A REMOTE TTY?
	DPB	T2,LDPADT	;  IF IT IS, THEN CLEAR HIS TIMER
>
	MOVE	T3,LDBDDB(U)	;KILL OR COMMAND?
	TLNN	T3,LDBCMF!LDBDET;FORCED COMMAND OR CLEANUP REQUIRED?
	TLNN	T3,LDBCMK	;NO, FORCED KJOB?
	JRST	TTYCM7		;NO.
	JRST	TTYCM5		;FORCED KJOB!
;DO FORCED COMMANDS OR CLEANUP 1ST, THEN FORCED KJOBS, THEN TYPED-IN COMMANDS

TTYCM7:	HRRM	U,.CPCML##	;MUST BE SAVED WHEN TTCMCA IS USED
	SCNOFF
	MOVE	T1,LDBTIT(U)	;GET TYPEIN CHAR ADR
	PUSHJ	P,CTISBP	; AND DEFINE IT AS THE INPUT BYTE POINTER
	SCNON
	HRRI	T3," "		;PRIME THE TYI ROUTINE
	TLNE	T3,LDBCMF	;FORCED COMMAND?
	MOVEI	T3,12		;YES. PREVENT EXTRA ARGUMENTS
	PUSHJ	P,CTISLC	;SAY IT IS LAST CHAR READ
	PUSHJ	P,FNDPDB##	;ADDRESS OF PDB
	  JFCL
	POPJ	P,0

TTYCM5:	MOVEI	T1,TTFCXC	;FORCE HALT 1ST SINCE IF TTKJOB IS CALLED DURING A COMMAND
	SKIPGE	JBTSTS##(J)	;MUST BE A JOB.  IS IT RUNNING
	JRST	TTYCM6		;NO.  JUST KILL IT
	MOVSI	T1,LDBCMK	;CLEAR KILL
	ANDCAM	T1,LDBDDB(U)	;FLAG
	MOVEI	T1,TTFCXK
TTYCM6:	PUSHJ	P,TTFORC	;FORCE COMMAND

;DON'T CALL CMDCLR, OR DELAYED COMMAND WILL NEVER BE SEEN AGAIN

	MOVE	T4,LINSAV##	;FIND LINE
	JRST	TTCM4A		;AGAIN
TTKJOB::PUSHJ	P,CNCMOD	;CONSOLE TO COMMAND LEVEL
	MOVSI	T1,LDBCMK	;SET KILL REQUEST
	IORM	T1,LDBDDB(U)	;IN LDB
	HRRZ	F,LDBDDB(U)
	SKIPE	J,F
	LDB	J,PJOBN##
	AOS	COMCNT##	;MAKE COMCON SEE IT
	SKIPL	JBTSTS##(J)	;SKIP IF JOB IS IN RUN STATE
				; THIS DEPENDS UPON:
				; 1. RUN BIT BEING SIGN OF JBTSTS
				; 2. J=0 IF NO JOB
				; 3. JBTSTS+0 = 0
	PJRST	CMDSET


;TTHALT  --  HALT THE JOB ATTACHED TO THE TERMINAL
;
;THIS ROUTINE DOES NOT SET TERMINAL TO COMMAND LEVEL BECAUSE JACCT
;PROGRAMS MAY STILL NEED TO TYPEOUT AND THAT WOULD BLOCK THEM IN TO STATE.

TTHALT:	MOVEI	T1,TTFCXC	;HALT COMMAND INDEX
	PJRST	TTFORC		;FORCE THE ↑C
;ROUTINES TO ATTACH TERMINAL TO A JOB

;1) CALL WHEN COMMAND DECODER DECIDES TO CREATE A JOB DUE TO
;A COMMAND BEING TYPED IN. THE LDB WILL ALREADY HAVE BEEN
;SET UP, BUT IT IS NOT YET LINKED TO A DDB
;
;CALL:	MOVE LINE,ADDRESS OF LDB
;	MOVE J,NEW JOB NUMBER
;	PUSHJ P,TTYATI
;	  ERROR RETURN	;ALREADY SOMEONE THERE (DDB POINTS AT HIM), OR
;			;NO MORE FREE DDB'S (DDB CONTAINS 0)
;	OK RETURN	;DDB, DDBLDB, AND LDBDDB SET UP
;
;2) CALL FROM COMMAND DECODER ON AN ATTACH COMMAND.
;
;CALL:	MOVE LINE,ADDRESS OF LDB
;	MOVE J,JOB TO ATTACH TO
;	PUSHJ P,TTYATT
;	  ERROR RETURN	;SOMEONE ALREADY ATTACHED (DDB POINTS TO HIM) OR
;			;NO SUCH DDB (DDB=0)
;	OK RETURN	;DDB, LDBDDB, NEW DDBLDB SET UP. OLD DDBLDB CLEARED

IFN FTATTACH,<

TTYATT::PUSH	P,U
	PUSHJ	P,TTYISA	;SEE IF DDB FOR TARGET JOB CAN BE ATTACHED
	  JRST	LPOPJ##		;NO, CAN'T DO IT
IFE FTPI,<JUMPE T1,TTYAT2>	;JUMP IF NO JOB IS ATTACHED TO LINE
IFN FTPI,<JUMPE T1,TTYAT1>	;JUMP IF DETACHED BUT SIGNAL DETACHING
	MOVEM	T1,(P)		;SAVE LDB OF TARGET JOB
	LDB	T1,LDPLNO	;OPERATOR DOING PREEMPTIVE ATTACH
				; GET OPERATOR'S LINE NUMBER
	EXCH	U,0(P)		;GET LDB OF OBJECT JOB
	LDB	T3,LDPLNO	;GET ITS LINE NUMBER TOO
	CAIE	T3,0(T1)	;ARE THEY THE SAME? (OPR ATTACHING
				; TO HIMSELF?)
	PUSHJ	P,PTYDET	;NO. DETACH OBJECT JOB, NOW IN LINE.
				; MUST RESPECT F
				;F NOW POINTS TO JOB BEING
				;PICKED UP BY TERMINAL IN 0(P)
	JRST	TTYAT2		;GO DO THE ATTACH
IFN FTPI,<
TTYAT1:	PUSHJ	P,SIGDET	;SIGNAL DETACHING
	JRST	TTYAT2		;GO DO THE ATTACH
>
> ;END IFN FTATTACH
TTYATI::
IFN FTMP,<
	PUSHJ	P,INTLVL##	;IF AT UUO LEVEL
	  PUSHJ	P,ONCPU0##	;AVOID RACES WITH COMCON
>
	PUSH	P,U		;SAVE LINE DATA BLOCK ADDRESS
	PUSHJ	P,TTYSRC	;SEE IF THERE'S ALREADY A DDB. SHOULDNT BE.
	  PUSHJ P,DDBSRC	;OK. GET A NEW DDB.
	    JRST LPOPJ##	;ERROR. EITHER TTYSRC WON OR DDBSRC LOST
TTYAT2:	MOVE	U,0(P)		;GET LDB ADDR FROM STACK
	PUSH	P,F		;AND SAVE NEW DDB ADDRESS
	HRRZ	F,LDBDDB(U)	;GET OLD DDB IF ANY
	SKIPE	F		;ANY THERE?
	PUSHJ	P,TTYDT1	;YES. DETACH FROM IT BUT DON'T SET MONITOR CODE
	SKIPN	U		;SKIP IF LDB WAS FOUND
	PUSHJ	P,TTYKLQ	;NO, KILL OFF DDB
	MOVE	F,0(P)		;RESTORE NEW DDB ADDRESS
IFN FTMODM,<
	MOVE	U,-1(P)		;GET LDB ADDRESS, FOR DS POINTER
	MOVSI	T1,LDBCMF
	TDNE	T1,LDBDDB(U)
	JRST	TTYAT3
	MOVE	T1,LDBDCH(U)	;LOOK AT DATA SET BIT
	TRNN	T1,LDRREM	;IF NETWORK OR
	TRNN	T1,LDRDSD	;IF NOT A DATA SET
	JRST	TTYAT3		;NO DSCTAB ENTRY
	LDB	U,LDPDSC	;GET DATASET TABLE INDEX
	MOVEI	T1,0		;CLEAR TIME FIELD OF DATASET ENTRY
	DPB	T1,DSTMPL	; ..
>
TTYAT3:	MOVE	U,-1(P)		;ATTACH LDB FROM STACK TO DDB
	MOVE	T1,[XWD TTYATC,ASSCON]	;SET ATTACHED AND ASSIGNED BITS
	IORM	T1,DEVMOD(F)	;IN THE DEV DATA BLOCK
	HRRM	F,LDBDDB(U)	;SET LINK FROM DDB TO LDB
	HRRM	U,DDBLDB(F)	;AND LINK FROM LDB TO DDB
	PUSHJ	P,SETDVL##	;AND JOB NUMBER IN DDB
	HRRZM	F,TTYTAB##(J)	;STORE CONTROLLING DDB BY JOB NUMBER
	PUSHJ	P,SCNNAM	;SET UP PHYSICAL LINE NAME AND PUNIT
IFN FTNET,<PUSHJ P,SETSTA>	;SET CORRECT STATION NUMBER

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

;THIS CODE MAKES SURE BATCH BIT STAYS CORRECT

IFN FTATTA&FTTLIM,<
	PUSHJ	P,CTLJBU##	;GET PTY DDB IF ANY
	JUMPL	T1,TTYAT5
	MOVSI	T1,DVDIBP	;GET BATCH PTY BIT
	MOVE	T2,JBTLIM##(J)	;GET JBTLIM
	TDNN	T1,DEVCHR(F)	;IS IT A BATCH PTY?
	JRST	TTYAT4		;NO
	TLON	T2,(JB.LBT)	;YES, MAKE IT A BATCH JOB
	AOS	BATNUM##	;INCREMENT # OF BATCH JOBS
	MOVEM	T2,JBTLIM##(J)	;RESTORE JBTLIM
TTYAT4:
> ;END FTATTA&FTTLIM&FTPTYUUO

IFN FTPI,<PUSHJ	P,SIGDET>	;SIGNAL ATTACH (SAME AS DETACH)

TTYAT5:
IFN FTCIMP,<			;[arpa]
	MOVEI	T1,LDRIMP	;[arpa] IMP CONNECTION?
	TDNE	T1,LDBDCH(U)	;[arpa] ....
	  PUSHJ	P,IMPATT##	;[arpa] YES - LINK UP
>				;[arpa]
	POP	P,F
IFN	FTTLIM,<
	MOVSI	T1,(JB.LTL)	;GET DETACH TIME UNIT BIT
	TDNN	T1,JBTLIM##(J)	;SEE IF SET
	  JRST	TTYAT6		;NO -- LEAVE ALONE
	ANDCAM	T1,JBTLIM##(J)	;YES -- CLEAR IT
	MOVEI	T1,0		;NO TIME UNIT NOW
	DPB	T1,JBYLTM##	;CLEAR
TTYAT6:
> ;END IFN FTTLIM
	JRST	UPOPJ1##	;SKIP RETURN TO COMCON.
;SUBROUTINE TO LOOK FOR POSSIBLE LINE ALREADY ATTACHED TO TARGET JOB
;ARGS	U=LINE ATTACH WAS TYPED OR
;	J=JOB NUMBER OF TARGET JOB
;VALUES	T1=ADDR OF LDB ATTACHED TO TARGET JOB OR 0 IF NONE
;NON-SKIP RETURN IF NO DDB FOR TARGET JOB OR DDB FOUND BUT MANY NOT ATTACH
;SKIP RETURN IF DDB FOUND AND MAY ATTACH TO IT

TTYISA::PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	PUSH	P,U		;SAVE LINE BLOCK ADR OF GUY TYPING COMMAND
	PUSHJ	P,TTYSRC	;FIND THE DDB CONTROLLING THAT JOB
	  JRST LPOPJ##		;THERE ISN'T ANY. COMCON HAS GOOFED?
	SETZ	T1,
	JUMPE	U,LPOPJ1##	;IF NONE ATTACHED, GO ATTACH.
	EXCH	U,0(P)		;SOMEONE IS ATTACHED. ONLY THE OPERATOR
				;MAY USURP THE EXISTING CONNECTION
	PUSH	P,F		;SAVE NEW DDB
	HRRZ	F,LDBDDB(U)	;DDB OF OLD USER
	SKIPE	T1,F		;IF F=0, MAKE T1 0, SINCE PJOBN IS MEANINGLESS IF F=0
	LDB	T1,PJOBN##	;HIS JOB NUMBER
	LDB	P1,LDPLNO	;GET TERMINAL LINE # IN P1
	SUBI	P1,PTYOFS##	;SUBTRACT OFFSET OF PTY0
	JUMPL	P1,TTYIS1	;SEE IF A PTY
	CAIGE	P1,PTYN##	; ..
	SKIPA	F,PTYTAB##(P1)	;IT IS A PTY, GET DDB
TTYIS1:	TDZA	P1,P1		;NOT A PTY, USE JOB 0
	LDB	P1,PJOBN##	;GET JOB OWNING PTY
	POP	P,F		;RESTORE F
	MOVE	P2,FSFPPN##	;GET [1,2]
	CAME	P2,JBTPPN##(T1)	;IS JOB THAT TYPED COMMAND [1,2]?
	CAMN	P2,JBTPPN##(P1)	;OR COMMAND TYPED BY SON OF OPR?
	JRST	TPOPJ1##	;YES, ATTACH IS LEGAL

	HRRZ	T1,OPRLDB##
	CAIE	T1,0(U)		;IS THIS THE OPR?
	JRST	TPOPJ##		;NO. DISCARD OBJECT JOB'S LDB FROM
	JRST	TPOPJ1##	;STACK, AND GIVE ERROR RETURN TO COMCON
				;WITH DDB POINTING AT GUY ALREADY ATTACHED
;ROUTINE TO DETACH TERMINAL FROM A JOB.
;CALL:	MOVE F,ADDRESS OF TTY DDB TO BE DETACHED
;	MOVE U,LDB  ADDRESS IF ENTRY AT PTYDTC
;	PUSHJ P,TTYDET
;	ALWAYS RETURN HERE

;CALLED FROM TTYATT AND COMCON (DETACH COMMAND)
;KILLS DDB IF NOT ATTACHED, ASSIGNED, OR INITED
;CLEARS LINKS TO DDB
;RESPECTS DDB


TTYDTC::TDZA	T2,T2		;FLAG TTYDTC ENTRY
TTYDET::MOVEI	T2,1		;SAME FOR TTYDET
IFN FTPI,<
	PUSH	P,T2		;SAVE T2
	PUSHJ	P,SIGDET
	POP	P,T2		;RESTORE IT
>
	HRRZ	U,DDBLDB(F)	;GET LDB ADDRESS
	LDB	T1,LDPLNO	;GET LINE NUMBER
	CAIN	T1,FRCLIN##	;RUNNING ON FRCLIN?
	JRST	@[EXP PTYDTC,PTYDET](T2)  ;YES, SKIP LOGGED OUT CHECK
	LDB	T1,PJOBN##	;GET JOB NUMBER
	MOVE	T1,JBTSTS##(T1)	;IS HE LOGGED IN?
	TLNE	T1,JLOG		; ..
	JRST	@[EXP PTYDTC,PTYDET](T2) ;YES, DISPATCH TO PTYDET
	LDB	T2,PJOBN##	;GET JOB NUM
	MOVE	T1,[SIXBIT/LOGOUT/]	;DON'T CLEAR
	CAMN	T1,JBTNAM##(T2)	;FOR LOGOUT SINCE USER COULD
	JRST	TTKJOB		;THEN GET OUT OVER QUOTA
	MOVSI	T1,JACCT	;CLEAR JACCT
	ANDCAM	T1,JBTSTS##(T2)	;IN STATUS
	JRST	TTKJOB		;GO KILL HIM
PTYDTC::LDB	T1,PJOBN##	;GET JOB NUMBER FROM DDB
	MOVSI	T2,CMWB		;AND COMMAND WAIT BIT
IFN FTMP,<CAME T1,COMJOB##>	;CURRENT JOB IN COMCON?
	TDNE	T2,JBTSTS##(T1)	;OR JOB IN COMMAND WAIT?
	JRST	[MOVSI	T1,LDBDET ;TELL COMRET TO CLEAN UP
		 IORM	T1,LDBDDB(U) ;JOB/COMMAND AT COMMAND EXIT
		 PJRST	DETCHK]	;WAIT FOR DETACH AND RETURN
PTYDET::PUSHJ	P,TTYDT1	;DISCONNECT DDB FROM LDB
	JUMPE	U,TTYKLQ	;IF NO LDB KILL OFF DDB
	PUSHJ	P,CNCMOD	;MAKE SURE LDB AT TOP LEVEL

;ROUTINE TO KILL DDB IF IT IS AN IDLE TTY DDB


TTYKLQ::PUSH	P,T1		;RESPECT T1
	MOVE	T1,DEVMOD(F)	;GET DEVICE MODE AND USE BITS
	TLNE	T1,DVTTY	;IS IT A TTY DDB?
	TDNE	T1,[XWD TTYATC,ASSCON+ASSPRG]	;YES, ANY REASON TO KEEP DDB?
	JRST	TPOPJ##		;YES.
	PUSHJ	P,TTYKIL	;NO. GO KILL THE DDB
	JRST	TPOPJ##		;AND RESTORE T1 ON RETURN
;SUBROUTINE TO DISCONNECT A TERMINAL FROM A JOB WITHOUT SETTING TERMINAL TO MONITOR LEVEL
;THIS IS SO ATTACH UUO WILL LEAVE TERMINAL AT ITS ORIGINAL LEVEL (MONITOR OR USER MODE)

TTYDT1:	HRRZ	U,DDBLDB(F)	;GET LINKED LINE ADDRESS
	HLLZS	DDBLDB(F)	;DISCONNECT LDB FROM DDB
	JUMPE	U,TTYDTX	;IF NO LDB, KILL OFF DDB
	HLLZS	LDBDDB(U)	;DISCONNECT DDB FROM LDB
	HRRZS	DEVNAM(F)	;CLEAR LH OF DEVNAM TO NOT CONFUSE DEVCHR, ETC.
				;KEEP RH FOR SYSTAT, ETC.
IFN FTDAEM!FTTLIM,<
	LDB	T1,PJOBN##	;SEE IF THIS JOB WAITING FOR DAEMON
>
IFN FTTLIM,<
	MOVSI	T2,(JB.LBT)	;BATCH BIT
	TDNE	T2,JBTLIM##(T1)	;IF WAS BATCH JOB
	SOS	BATNUM##	;DECR. BATCH JOB COUNT
	ANDCAM	T2,JBTLIM##(T1)	;CLEAR BIT SO OPERATOR CAN DETACH
>
IFN FTDAEM,<
	MOVE	T1,JBTSTS##(T1)	;GET JOB STATUS WORD
	TRNN	T1,JDC		;DCORE COMMAND WAITING?
>
	PUSHJ	P,TYIEAT	;NO. CLEAR ANY PENDING COMMAND
	MOVE	T1,LDBDCH(U)	;GET LINE CHARACTERISTICS
	TRNE	T1,LDRPTY	;A PTY LINE?
	PUSHJ	P,PTMNMD##	;YES. WAKE CONTROLLER
TTYDTX:	POPJ	P,

IFN FTPI,<
SIGDET:	SIGNAL	C$DATT
	  POPJ	P,
	POPJ	P,
>

;ROUTINE TO MAKE SURE A LINE IS DETACHED BEFORE PROCEDING
;CALL WITH U POINTING AT THE LDB IN QUESTION
DETCHK:	PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##	;SET TO CURRENT JOB
DETCH1:	MOVSI	T1,LDBDET	;WAITING FOR COMMAND
	TDZN	T1,LDBDDB(U)	; TO COMPLETE?
	JRST	JPOPJ##		;NO
	PUSHJ	P,SLEEPF##	;YES, WAIT UNTIL ITS DONE
	JRST	DETCH1		;TRY AGAIN
;ROUTINE TO RELEASE A TTY DDB. CALL WITH DDB SET UP.


TTYREL::MOVE	T1,[XWD IOW,IOACT]	;CLEAR OUT S
	ANDM	T1,DEVIOS(F)	; IN CORE
	SKIPE	DINITF##	;IN SYSINI?
	JRST	TTYRL2		;YES--SKIP THIS
	PUSHJ	P,SAVE1##	;SAVE CHANNEL NUMBER
	MOVEI	P1,0		;START AT CHANNEL ZERO
TTYRL0:	PUSHJ	P,NXTCH##	;NEXT CHANNEL
	  JRST	TTYRL1		;ALL CHANNELS HAVE BEEN LOOKED AT
	SOS	P1		;ADJUST P1
	CAIN	P1,@-1(P)	;CHANNEL BEING RELEASED
	AOJA	P1,TTYRL0	;YES
	CAIE	T1,(F)		;NO SAME DDB OPEN ON ANOTHER CHANNEL?
	AOJA	P1,TTYRL0	;NO
	JRST	TTYRS1		;YES, DON'T MAKE THE DDB GO AWAY
TTYRL1:
IFN FT2741&FTCAFE <
	HRRZ	U,DDBLDB(F)	;GET LINE BLOCK ADR
	JUMPE	U,TTYRL2	;BYPASS IF NONE
	MOVSI	T1,LILAPL	;BIT FOR APL MODE
	ANDCAM	T1,LDBISR(U)	;CLEAR APL MODE
>;END OF IFN FT2741
TTYRL2:	MOVE	T1,[XWD TTYATC,ASSCON]	;IS TTY ATTACHED OR ASSIGNED?
	TDNE	T1,DEVMOD(F)	; ..
	JRST	TTYRS1		;YES. KEEP DDB AROUND. RETURN.
;	JRST	TTYKIL		;NO. GO DISCARD DDB.
;ROUTINE TO CLEAR A TTY DDB AND MAKE IT AVAILABLE TO THE POOL
;CALL:	MOVE F,ADDRESS OF DEVICE DATA BLOCK KNOWN TO BE THROUGH USE.
;	PUSHJ P,TTYKIL
;	ALWAYS RETURN HERE
;RESPECTS F & S, CLOBBERS T1


TTYKIL::SETZM	DEVLOG(F)	;CLEAR LOGICAL NAME
	MOVSI	T1,IOFST	;INITIAL STATE OF S WORD
	MOVEM	T1,DEVIOS(F)	;PLACE IN CORE STATUS WORD
IFN FTPI,<
	SKIPE	DEVPSI(F)	;USER INTERRUPTING ON THIS
	PUSHJ	P,PSIRMV##	;YES, REMOVE PSI LINKS
>
	PUSHJ	P,CLRDVL##	;NO JOB OWNS IT ANY MORE.
IFN FTLINK,<			;[link]
	PUSHJ	P,LNKBRK##	;[link] CUT OFF LINKS
>				;[link]
	PUSH	P,U
	HRRZ	U,DDBLDB(F)	;GET LINK TO LINE DATA BLOCK
	JUMPE	U,TTYKL1	;BYPASS IF NO LINK.
	PUSHJ	P,TTYSTC	;PUT LINE AT COMMAND LEVEL
	PUSHJ	P,TTYCPT	;CLEAR PAPER TAPE BITS
	MOVSI	T1,LPLCLR	;CLEAR PAGE BITS
	ANDCAM	T1,LDBPAG(U)	;SO XON AND XOFF ARE ECHOED PROPERLY
	MOVSI	T1,LDLSSO!LDLBKA	;CLEAR THE STOP OUTPUT BIT	
	ANDCAM	T1,LDBDCH(U)	;IN THE DCH WORD
IFN FTCIMP,<			;[arpa]
	SETZM	LDBIMP(U)	;[arpa] CLEAN UP IMP PARTS OF LDB
	SETZM	LDBQUO(U)	;[arpa] ....
>				;[arpa]
	PUSHJ	P,CLRIM1	;MAKE SURE NOT IN IMAGE MODE
	PUSH	P,S		;IN CASE SOME CALLER SOMEWHERE CARES
	MOVEI	S,0		;CLEAR ALL THOSE BITS IN LDBDCH
	PUSHJ	P,UUOLDB	;CLEAR OUT LDB
	POP	P,S		;THIS IS REALLY SUPERCAUTION
TTYKL1:	MOVSI	T1,DEPRAS	;TEST FOR DDB RESTRICTED
	TDNE	T1,DEVSTA(F)	;IS IT A RESTRICTED TTY?
	JRST	[POP P,U
		 JRST TTYRS1]	;YES, SO KEEP DDB
	SETZM	DEVNAM(F)	;CLEAR PHYSICAL NAME
	HLLZS	LDBDDB(U)	;REMOVE LINK TO DEAD DDB
	HLLZS	DDBLDB(F)	;REMOVE LINK FROM DDB TO LINE DATA BLOCK
	MOVE	T1,[XWD TTYUSE+TTYATC,ASSCON+ASSPRG]
	ANDCAB	T1,DEVMOD(F)	;LAST CLEAR THESE, MAKING DDB AVAILABLE
	JRST	UPOPJ##		;AND RETURN TO CALLER.
;SUBROUTINE CALLED ON RESET FROM UUOCON


TTYRES::PUSHJ	P,SAVE1##
	MOVEI	P1,JS.NTO
	TDNE	P1,JBTSTS##(J)
	XORB	P1,JBTSTS##(J)
	ANDI	P1,JS.NTO
	MOVEI	F,SCNDDB
TTYRSA:	LDB	T1,PJOBN##
	CAIE	T1,(J)
	JRST	TTYRSB
	JUMPN	P1,TTYRSC
	SETZB	T1,DEVSTS(F)
	DPB	T1,BYTCNT
TTYRSC:	MOVE	T1,[TTYATC,,ASSCON]
	TDNN	T1,DEVMOD(F)
	PUSHJ	P,TTYKIL
TTYRSB:	HLRZ	F,DEVSER(F)
	MOVE	T1,DEVMOD(F)
	TLNE	T1,DVTTY
	JRST	TTYRSA
	HRRZ	F,TTYTAB##(J)	;GET CONTROLLING DDB ADDRESS
	JUMPE	F,CPOPJ##	;REALLY HAS TO BE ONE
TTYRS1:	MOVE	S,[IOLBKA,,IOSBKA!IOSTEC!IOSFCS+D] ;GET BITS

;THE FOLLOWING CHECK FOR NOT LOGGED IN, RUNNING "LOGIN"
; IS TO AVOID BREAKING ANCIENT "FEATURE" OF NOECHO GETTING
; SET BY LOGIN COMMAND.

	HRRZ	U,DDBLDB(F)	;LINK TO LDB
	JUMPE	U,TTYRS2	;NOT BATCH IS DETACHED
	PUSHJ	P,PTBTCH##
	  JRST	TTYRS2
	MOVE	T1,JBTSTS##(J)	;GET THIS STATUS
	MOVE	T2,JBTPRG##(J)	; AND PROGRAM NAME
	TLNN	T1,JLOG		;IS HE NOT LOGGED IN?
	CAME	T2,[SIXBIT/LOGIN/] ; AND RUNNING LOGIN
TTYRS2:	IORI	S,IOSNEC	;NOT BOTH, WE CAN CLEAR NOECHO
	ANDCAB	S,DEVIOS(F)	;CLEAR THESE BITS ON RESET
	JUMPE	U,CPOPJ##	;SKIP IT IF DETACHED
	MOVEI	T1,0		;CLEAR THE AUTO
	DPB	T1,LDPACR	;CRLF COUNTER
	PUSHJ	P,CLRIM1	;CLEAR IMAGE MODE
	MOVSI	T1,LDLBKA	;THE BREAK-ON-ALL-CHARACTERS BIT
	ANDCAM	T1,LDBDCH(U)	;CLEAR IN LDB SINCE TTYUSR ALREADY CALLED
				; AND WILL HAVE SET IT IF IOLBKA WAS SET
	PUSHJ	P,UUOLDB	;AND MAKE LDB AGREE
	PJRST	SETCHP		;FORCE CHANGE OF CHARACTERISTICS
;SUBROUTINE TO RETURN ONE CHARACTER FROM THE INPUT BUFFER. CHARACTER
;RETURNED IN T3.

COMTYI::PUSH	P,T2		;SAVE AC FOR OUTSIDE WORLD
	PUSHJ	P,CTIGLC	;GET THE LAST CHARACTER
	SKIPN	T3		;IS ANYTHING THERE FROM BEFORE?
	MOVEI	T3,12		;NO. ASSUME END OF LINE
	PUSHJ	P,SPCHEK	;YES. WAS IT A BREAK?
	  JFCL
	TLNN	T1,CHBRK	; ..
COMTI1:	PUSHJ	P,CTIGNC	;NO. GET ANOTHER CHARACTER (CCTYI OR ONCE)
	ANDI	T3,177		;COMCON DOESN'T WANT PARITY
	PUSHJ	P,SPCHEK	;CONVERT TO CONSISTENT BREAKS
	  JFCL			;ORDINARY CHARACTER
	TLNE	T1,CHCRET	;CARRIAGE RETURN?
	JRST	COMTI1		;YES. GO GET LINEFEED INSTEAD
	TLNE	T1,CHBRK	;BREAK?
	MOVEI	T3,12		;YES--MAKE INTO LINE FEED
	TLNE	T1,CHCNC	;IS THIS A CONTROL-C?
	MOVEI	T3,3		;YES--CONTROL-C IS STRONGER THAN LF
	PUSHJ	P,CTISLC	;SAY THAT THIS IS THE "LAST CHAR"
COMTIX:	PJRST	T2POPJ##	;RESTORE AC T2 AND RETURN


;SUBROUTINE TO SEND 1 CHAR, SENDING CONTROL CHARS AS ↑X
;OTHERWISE, SAME AS COMTYO

USEARO::PUSHJ	P,SPCHEK	;SPECIAL CHAR?
	  JRST	COMTYO		;NO, FORGET IT
	TLNN	T1,CHUAE	;ECHO AS ↑X?
	  JRST	COMTYO		;NO, GO ECHO NORMALLY
	PUSH	P,T3		;SAVE THE CHAR
	MOVEI	T3,336		;GET AN ARROW
	PUSHJ	P,COMTYO	;SEND IT
	POP	P,T3		;RESTORE CHAR
	TRC	T3,300		;CONVERT TO LETTER
;;	JRST	COMTYO		;AND GO TYPE IT


;SUBROUTINE TO SEND 1 CHARACTER, CHARACTER IN T3.
;PRESERVES T2 & T3

COMTYO::PUSH	P,T2		;SAVE AC
	PUSH	P,T3
	ANDI	T3,177		;SAVE PUSHJ TO PEVEN8, DO IT HERE
	MOVSI	T2,CHEPAR	;GET PARITY BIT
	TDNN	T2,CHTABL(T3)	;IS CHARACTER ALREADY EVEN PARITY?
	TRO	T3,200		;NO, MAKE IT SO
	PUSHJ	P,@.CPTOA##	;CALL  CCTYO, CTYWAT, OR ONCE ROUTINE
	POP	P,T3		;RESTORE
	JRST	T2POPJ##	; AC'S AND RETURN
;ROUTINE TO SWITCH TERMINAL TO USER PROGRAM LEVEL AND START USER RUNNING

TTYUSW::TDZA	S,S		;DON'T CLEAR WAIT BITS
TTYUSR::MOVE	S,[XWD IOW,IOACT]	;CLEAR WAIT BITS
	HRRZ	F,LDBDDB(U)	;GET ATTACHED DDB IF ANY
	JUMPE	F,TTYUS1	;JUMP IF NOT ATTACHED
	ANDCAB	S,DEVIOS(F)	; ..
	MOVSI	T1,LDLBKA	;THE VOLATILE BREAK-ON-ALL BIT
	TLNE	S,IOLBKA	;NEED TO RE-SET IT IN LDB?
	IORM	T1,LDBDCH(U)	;YES
	MOVSI	S,IOLBKA	;NOW CLEAR OUT
	ANDCAB	S,DEVIOS(F)	; ANNOYING TEMP BIT
	PUSHJ	P,UUOLDB	;MAKE LINE AND DEVIOS AGREE
TTYUS1:	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS THIS A PTY?
	PUSHJ	P,PTMNMZ##	;YES. TELL CONTROLLER
	MOVSI	T1,LDLCOM	;PUT TERMINAL IN USER MODE
	ANDCAM	T1,LDBDCH(U)	;MAY BE DETACHED, BUT WILL WAIT
				; AT UUO LEVEL IF NEEDED
	PJRST	SETRUN##	;SET USER'S RUN BIT AND RETURN



TTYSTC::HLL	U,LDBDCH(U)	;SEE IF THIS LINE IS SLAVED
	MOVSI	T1,LDLCOM	;PREPARE TO SET BIT
	TLNN	U,LDLSLV	;SLAVED?
IFN FTMIC,<			;IF MIC
	IORM	T1,LDBDCH(U)	;NO. SET COMMAND BIT
	PUSHJ	P,MICWAK	;WAKE MIC IF NECESSARY
> ;END OF IF MIC
IFE FTMIC,<IORB T1,LDBDCH(U)>	;NO, SET COMMAND BIT
	TRNE	T1,LDRPTY	;PTY-DRIVEN LINE?
	PUSHJ	P,PTMNMD##	;YES. TELL CONTROLLER
TTYSTR::MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS IT A PTY?
	PUSHJ	P,PTYPE##	;YES. WAKE THE PTY CONTROLLER
	PUSHJ	P,COMQ		;AT COMMAND LEVEL?
	  PJRST NOCTRO		;NO. JUST CLEAR ↑O BIT
	PUSHJ	P,TYIEAT	;YES. CLEAR THE COMMAND IN CASE MORE
	PUSHJ	P,STRTDL	;ECHO ONE DEFERRED LINE IF NECESSARY
	SKIPLE	LDBBKC(U)	;ANY MORE COMMANDS?
	PUSHJ	P,COMSET	;MAYBE. SET BIT IF AT COM LEVEL
	PJRST	NOCTRO		;CLEAR OSU AND RETURN
;HERE AT COMPLETION OF A COMMAND

TTYCMR::PUSH	P,T1		;SAVE PREVIOUS LDPCMX
	TRNN	F,-1		;ANY JOB?
	PUSHJ	P,TTYCPT	;NO. CLEAR PAPER-TAPE BITS
	AOS	T1,LINSAV##
	CAIL	T1,TTPLEN##
	SETZM	LINSAV##
	HLL	T2,LDBDDB(U)	;GET COMMAND REQUEST BITS
	POP	P,T1		;COMMAND JUST FINISHED
	LDB	T3,LDPCMX	;CURRENT
	CAME	T1,T3		;CHANGED?
	TLNN	T2,LDBCMF	;FORCED
	SKIPA			;NO CHANGE OR NOT FORCED
	POPJ	P,		;NEW FORCED-DO IT
	MOVEI	T1,L2RECS	;SET EAT-COMMAND-SYNC BIT
	TLNN	T2,LDBCMF	;(UNLESS FORCED COMMAND)
	IORM	T1,LDBBY2(U)	;IN LINE DATA BLOCK
	MOVSI	T1,LDBCMR+LDBCMF;CLEAR COMMAND REQUEST BITS
	ANDCAB	T1,LDBDDB(U)	;IN BASE WORD OF LDB
	MOVE	T1,LDBDCH(U)	;GET THE LINE'S CHARACTERISTIC
	TLNN	T1,LDLBKA+LDLIMI;ARE WE BREAKING ON ALL CHARACTERS
				; OR IN IMAGE MODE?
	JRST	TTCMR1		;NO, CONTINUE ON
	SKIPLE	LDBTIC(U)	;YES, DO WE HAVE ANY CHARACTERS
				; IN THE INPUT BUFFER?
	PUSHJ	P,RCVWAK	;YES, WAKE THE JOB
				;NO,...
TTCMR1::MOVE	T1,LDBDDB(U)	;GET THE LINES LDBDDB & CONTINUE
	TLNN	T1,LDBCMK	;FORCED KJOB PENDING?
IFN FTMIC,<			;IF MIC
	PUSHJ	P,CMDCLR	;NO, CLEAR COMMAND BIT
	PJRST	MICWAK		;WAKE MIC UP IF NEC & RETURN TO COMCON
> ;END OF IF MIC
IFE FTMIC,<			;IF NOT MIC
	PJRST	CMDCLR		;NO, CLEAR COMMAND BIT
	POPJ	P,0		;YES, DO NOT CLEAR COMMAND BIT
> ;END OF IF NOT MIC
	SUBTTL	SUBROUTINES FOR COMCON OR UUO LEVEL

;COMMON UUO LEVEL ROUTINES
;TYO7W IS USED TO TAKE A 7-BIT CHARACTER IN T3
; GO INTO I/O WAIT IF JOB DETACHED OR IF THE LINE'S
; OUTPUT BUFFER IS RATHER BIG, THEN PLACE THE CHARACTER IN OUTPUT
; STREAM, AND START OUTPUT IF NEEDED.
;TYO9W IS SAME, BUT ASSUMES PARITY AND NINTH BIT ARE AS DESIRED.
;TYO CHOOSES ONE OF THE ABOVE, DEPENDING ON MODE IN S
;CALL TYO9W WITH SIGN BIT OF T3 SET TO AVOID BLOCKING.  SIGN BIT CLEARED IF CHAR ACTUALLY OUTPUT
; (USED TO AVOID WTP STOPED ON CALL FROM TTMORE)
;CALL WITH DDB SET UP, CHARACTER IN T3.
;IF CALLED AT TYO, S MUST BE SET UP ALSO
TYO:	TRNN	S,I!PIMMOD	;IMAGE MODE USE OWN PARITY
TYO7W:	ANDI	T3,177
TYO9W:	MOVE	S,DEVIOS(F)
	TRNE	S,IODERR	;↑C TYPED ON TTYNNN
	JRST	[TLZ T3,(1B0)	;FLAG WE GOT CHAR
		 POPJ	P,]
	MOVSI	S,IO		;INDICATE OUTPUT
	IORB	S,DEVIOS(F)
	HRRZ	U,DDBLDB(F)	;GET LINE ADDR IF ANY
	JUMPN	U,TYOX		;ATTACHED, PROCEED
	JUMPL	T3,CPOPJ	;IF ASYNCHRONOUS RETURN
	PUSHJ	P,CKATOW	;WAIT FOR ATTACH
	SKIPA
TYOX:	PUSHJ	P,CKATO1
	MOVE	T1,TTFREN##	;MAKE SURE THERE'S SOME CHARACTER SPACE LEFT
	CAIGE	T1,3		;LEAVE 3 CHUNKS FOR SAFETY
	JRST	[JUMPGE T3,TYONFC ;NO,WAIT
		 POPJ	P,]
	MOVE	T1,LDBTOC(U)	;GET OUTPUT STREAM LENGTH
	CAML	T1,TIWRNN	;IS HE OVER QUOTA?
	JRST	[JUMPGE T3,TYOOBF ;WAIT IF ATTACHED
		 POPJ	P,]
IFN FTMIC,<
IFN FTMLOG,<
	SKIPN	LDBLOT(U)	;IS HE LOGGING
	JRST	TYO9M		;NO
	ADD	T1,LDBLOC(U)
	CAIL	T1,↑D100
	JRST	MICLGX		;GO WAKE UP MIC
TYO9M:>	;END OF FTMLOG CONDITIONAL
>;END IFN FTMIC
	TLZ	T3,(1B0)	;FLAG WE GOT THE CHARACTER
	MOVE	T1,LDBDCH(U)	;CHECK FOR OUTPUT SUPPRESS
	SKIPL	LDBOFL(U)
	TRNE	T1,LDROSU	; ..
	POPJ	P,0		;NO. JUST RETURN DUE TO ↑O
TYO9A:
IFN FTLINK,<			;[link]
	PUSHJ	P,CHKLNK##	;[link] SEND CHAR (COMCON/UUO LEVEL) TO ANY LINKS
LnkCpy::			;[link] entry to avoid LnkSer recursion.
>				;[link]
	SCNOFF			;NO RACES
	STCHK	T3,LDBTOP(U)	;STORE CHARACTER IN CHUNKS
	AOS	LDBTOC(U)	;COUNT UP OUTPUT STREAM LENGTH
	SCNON			;ALLOW INTERRUPTS
IFN FTMIC,<			;IF MIC
	PUSHJ	P,MICPOS	;YES SET UP AND CHECK POSITION
> ;END OF IF MIC
	PJRST	TOPOKE		;START OUTPUT FOR THE LINE
TYOVRG:	SCNOFF			;NO INTERRUPTS
	SKIPE	T1,LDBTOT(U)	;IF ALREADY A GOOD POINTER
	JRST	TYOVR1		;DON'T WASTE A GOOD CHUNK
	PUSHJ	P,GETCKZ	;GET A CHUNK FROM FREELIST
	ADD	T1,[POINT 9,1]	;MAKE INTO A BYTE POINTER
	MOVEM	T1,LDBTOT(U)
TYOVR1:	MOVEM	T1,LDBTOP(U)	;PUT IN TYPEOUT STRING ADDRESSES
	SETZM	LDBTOC(U)	;MAKE SURE COUNT IS ZERO
	JRST	SONPPJ		;REENABLE INTERRUPTS AND RETURN


;HERE IF NO FREE CHUNKS
TYONFC:	PUSH	P,16		;ACS USED BY SETSLP
	PUSH	P,17
	PUSH	P,T3
	PUSH	P,U
	MOVEI	T1,5		;SLEEP FOR 5 SEC.
	PUSHJ	P,SLEEP##	; ..
	POP	P,U		;RESTORE AC(S
	HRRZ	F,LDBDDB(U)
	POP	P,T3
	POP	P,17
	POP	P,16
	JRST	TYO9W


IFN FTMIC&FTMLOG,<
MICLGX:	PUSHJ	P,MICWAK
	JUMPL	T3,TYO9M		;DON'T BLOCK IF FROM TTMORE
> ;END OF FTMLOG CONDITIONAL

;HERE IF OUTPUT BUFFER FULL
TYOOBF:	PUSHJ	P,TOWAT1
	JRST	TYO9W

;SUBROUTINE TO SETUP A BYTE COUNT AND POINTER TO A USER'S BUFFER
;CALLING SEQUENCE:
;	MOVE	S,DEVIOS(F)
;	HRRZ	P1,USER VIRTUAL ADDRESS OF BUFFER
;	PUSHJ	P,SRLPTR
;
;ON RETURN P1 IS A BYTE POINTER TO THE USER BUFFER AND P2 IS THE MAXIMUM
;BYTE COUNT FOR THE BUFFER.

SRLPTR:	ADD	P1,[POINT 7,2]	;ASSUME ASCII MODE (AND SKIP .BFCNT WORD)
	TRNE	S,PIMMOD	;PACKED IMAGE MODE?
	HRLI	P1,(POINT 8,)	;YES, USE 8-BIT BYTES
	TRNE	S,I		;REGULAR IMAGE MODE?
	HRLI	P1,(POINT 36,)	;YES, USE 36-BIT BYTES
	TRNN	S,I!PIMMOD	;ASCII MODE?
	IMULI	P2,5		;YES, 5 BYTES PER WORD
	TRNE	S,PIMMOD	;PACKED IMAGE MODE?
	IMULI	P2,4		;YES, 4 BYTES PER WORD
	POPJ	P,
;SUBROUTINE FOR COMMAND LEVEL OUTPUT


CCTYO::	JUMPE	U,CPOPJ##	;U MUST BE SET UP
IFN FTCIMP,<			;[arpa]
	ANDI	T3,177		;[arpa] COMPUTE PARITY HERE SINCE IMPSER CALLS
CCTYO9::			;[arpa] THIS ROUTINE TO OUTPUT TELNET CODES
>				;[arpa]
	MOVE	T1,LDBTOC(U)	;GET COUNT
	SUBI	T1,↑D200
	SKIPLE	T2,TTFREN##	;SPACE IN STRINGS?
	CAML	T1,TIWRNN	;YES. SPACE IN THIS GUY'S AREA?
	POPJ	P,0		;NO. QUIT.
	CAIL	T2,3
	SKIPN	TTFTAK		;IS THERE A FREE LIST?
	POPJ	P,		;NO--PUNT
IFE FTCIMP,<			;[arpa]
	ANDI	T3,177		;FORCE EVEN PARITY SINCE CCTYO NEVER DOES IMAGE
>				;[arpa]
	JRST	TYO9A		;YES. GO TYPE IT.

	$LOW			;MUST BE IN THE LOW SEGMENT FOR ONCE-ONLY
;SUBROUTINE TO PRINT ON CTY IN EMERGENCY OR ONCE-ONLY
; WHEN INTERRUPT SYSTEM CANNOT BE USED OR TRUSTED
;CALL:	MOVEI	T1,ADR OF ASCIZ MESSAGE
;	PUSHJ	P,CTYTYP
;	ALWAYS	RETURN

CTYTYP::HRLI	T1,440700	;FORM BYTE POINTER
CTYTYL:	ILDB	T3,T1		;GET NEXT CHARACTER
	JUMPE	T3,LCPOPJ	;END OF MESSAGE?
				;(CPOPJ IS IN HISEG, SO DON'T USE IT)
	PUSHJ	P,CTYWAT	;NO, PRINT IT ON CTY AND WAIT
	JRST	CTYTYL		;GO GET NEXT CHAR.



;ROUTINE RESIDING IN LOSEG TO COMPUTE PARITY.
; USED ONLY FOR EMERGENCY CTY OUTPUT ROUTINES.
; USES T1

CTYPAR:	MOVEI	T1,(T3)
	LSH	T1,-4		;FOLD INTO LOW 4 BITS
	XORI	T1,(T3)
	TRCE	T1,14		;CHECK BITS 32 AND 33
	TRNN	T1,14
	TRC	T3,200		;IF EVEN PARITY COMPLEMENT RESULTS
	TRCE	T1,3
	TRNN	T1,3
	TRC	T3,200		;IF EVEN PARITY COMPLEMENT RESULTS
	POPJ	P,		;RETURN
;SUBROUTINE FOR ERROR MESSAGE TO CTY DURING PARITY ERROR STOP
;CALL:	MOVEI	T3,CHARACTER
;	PUSHJ	P,CTYWAT
;	RETURN AFTER CHARACTER HAS BEEN TYPED
;NOTE:  DOES NOT USE INTERRUPT SYSTEM SO MESSAGE WILL GET OUT BEFORE HALT
;THIS SUB CALLED BY COMTYO WHEN COMTOA PATCHED

CTYWAT::PUSH	P,T1
	PUSHJ	P,CTYPAR	;COMPUTE PARITY WITH LOSEG ROUTINE

IFN FTKI10,<
	CONSZ	CTY,20		;WAIT FOR CTY TO BE IDLE
	JRST	.-1		;NO, SO NOT GARBLE ON GOING OUTPUT
	DATAO	CTY,T3		;YES, SEND OUT CHAR
	PUSHJ	P,OPRFIL
	CONSZ	CTY,20		;WAIT FOR CTY TO BE IDLE
	JRST	.-1		;NO, OTHERWISE HALT OR RESET WILL CLOBBER LAST CHAR
	JRST	OPRFI2		;YES, OK TO RETURN
>;END FTKI10

IFN FTKS10,<
	SKIPE	CTYOWD		;CAN WE TYPE YET ?
	JRST	.-1		;WAIT A WHILE
	TRO	T3,CTYOVL	;VALID FLAG
	MOVEM	T3,CTYOWD	;PUT UP FOR FRONT END TO SEE IT
	RDAPR	T1		;GET PROCESSOR PIA
	ANDI	T1,SP.PIA	;LEAVE ONLY THE PIA
	WRAPR	SP.SSF+SP.IFE(T1) ;INTERRUPT THE FRONTEND
	SKIPE	CTYOWD		;WAIT FOR CTY TO BE IDLE
	JRST	.-1		;OTHERWISE HALT OR RESET WILL CLOBBER LAST CHAR
	JRST	OPRFI2		;OK TO RETURN
>;IFN FTKS10

IFN FTKL10,<
	PUSHJ	P,SPCTYO##	;SEND CHAR OVER
	PUSHJ	P,SPCWTO##	;WAIT FOR OUTPUT TO COMPLETE
	  JRST	.-1
	JRST	OPRFI2		;RESTORE T1
				;AND RETURN
>;END IFN FTKL10
	$HIGH			;BACK TO THE HIGH SEGMENT
;SUBROUTINE TO CLEAR PAPER TAPE INPUT BITS, RETURNS LDBDCH IN T1
TTYCPT::MOVSI	T1,L2LTAP	;CLEAR TTY TAPE COMMAND BIT
	ANDCAM	T1,LDBBY2(U)	;IN BY2
	MOVEI	T1,L2RXON	;CLEAR XON IN EFFECT
	ANDCAB	T1,LDBBY2(U)	;AND RETURN NEW STATUS
	POPJ	P,		;RETURN

	$LOW			;MUST BE IN THE LOW SEG FOR EMERGENCIES

;SUBROUTINE TO ADD A DELAY FOR SLOW CTY'S
;CALL WITH:
;	MOVEI	T3,CHAR
;	PUSHJ	P,OPRFIL
;USED ONLY WITH PI SYSTEM OFF
OPRFIL::ANDI	T3,177		;ONLY CHAR BITS
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,0		;ASSUME NO FILLERS
	CAIN	T3,12		;LF GETS
	MOVEI	T1,CTYDLF##	;8 TICKS
	CAIN	T3,15		;CR GETS
	MOVEI	T1,CTYDCR##	;18 TICKS
	JUMPE	T1,OPRFI2	;RETURN
	ADDM	T1,TIME##	;UPDATE TIME
IFN FTKI10,<
OPRFI1:	CONSO	APR,XP.CLK	;DID CLOCK TICK?
	JRST	OPRFI1		;NO -- WAIT FOR IT
	CONO	APR,XP.CCF	;CLEAR CLOCK FLAG
>;END IFN FTKI10

IFN FTKS10,<
OPRFI1:	RDAPR	T1		;GET CLOCK FLAG
	TRNN	T1,SP.ITI	;DID CLOCK TICK ?
	JRST	OPRFI1		;NOT YET
	WRAPR	SP.CSF+SP.ITI	;CLEAR CLOCK FLAG
>;IFN FTKS10

IFN FTKL10,<
OPRFI1:	CONSO	TIM,TI.ITD	;CLOCK "TICK" ?
	JRST	OPRFI1		;NOT YET
	CONO	TIM,@ONCKLT##	;YES, CLEAR AND SET FOR ANOTHER "TICK"
>;END IFN FTKL10
	SOJG	T1,OPRFI1	;LOOP FOR WHOLE TIME
OPRFI2:	POP	P,T1		;--
LCPOPJ:	POPJ	P,		;LOCAL CPOPJ FOR USE WHEN HISEG ISN'T MAPPED
	$HIGH			;BACK TO THE HIGH SEGMENT
;ROUTINE TO FIND A FREE TTY DEVICE DATA BLOCK

;CALL FROM CLOCK LEVEL TO DO AN ATTACH ON A NEW JOB, OR
;FROM UUO LEVEL ON AN INIT OF A NEW LINE.

;CALL:	NO ARGUMENTS
;	PUSHJ P,DDBSRC
;	  ERROR RETURN		;NONE AVAILABLE. F=0. T1 CLOBBERED
;	OK RETURN		;ADDRESS IN F, TTYUSE SET IN DEVMOD
;				;RESPECTS J,U,T2.
;				;IF YOU DECIDE NOT TO USE DDB, YOU BETTER
;				;FREE IT UP AGAIN.


DDBSRC:	PUSHJ	P,DDBSR0	;TRY TO GET A DDB
	  SKIPA			;LOST -- TRY AGAIN
	PJRST	CPOPJ1##	;WE WON
DDBSR0:	MOVEI	F,TTYLST	;START OF THE TTY DDB'S
DDBSRA:	MOVSI	T1,TTYUSE	;FLAG THAT A DDB ISN'T FREE
	SCNOFF			;MAKE SURE NO CONFLICT HERE
	TDNN	T1,DEVMOD(F)	;IS THIS DDB FREE?
	JRST	DDBSR1		;YES. GO GRAB IT.
	SCNON			;NO. REENABLE PI SYSTEM
	HLRZ	F,DEVSER(F)	;LINK DOWN THE DDB CHAIN
	MOVE	T1,DEVMOD(F)	;MAKE SURE STILL A TTY DDB
	TLNE	T1,DVTTY	;IS IT?
	JUMPN	F,DDBSRA	;YES. (UNLESS END OF CHAIN)
	MOVEI	F,0		;NO MORE TTY DDB'S. WE LOSE.
	POPJ	P,0		;RETURN NON-SKIP, WITH 0 IN DDB

DDBSR1:	IORM	T1,DEVMOD(F)	;SET BIT SO WE HAVE THE DDB
	SCNON			;NOW PI'S CAN HAPPEN AGAIN
	PUSHJ	P,CLRDVL##	;CLEAR JOB NO. IN CASE OF JUNK
	MOVE	T1,[XWD TTYATC,ASSCON+ASSPRG]	;LIKEWISE MODE BITS
	ANDCAM	T1,DEVMOD(F)	; ..
	MOVSI	T1,DEPRAS	;GET THE RESTRICTED ASSIGN BIT
	ANDCAM	T1,DEVSTA(F)	;MAKE SURE IT'S CLEARED
	SETZM	DEVLOG(F)	;AND LOGICAL NAME
	MOVSI	T1,IOFST	;AND INITIAL S WORD
	MOVEM	T1,DEVIOS(F)	;WHICH SHOULD LEAVE IT PRETTY CLEAN
	JRST	CPOPJ1##	;SKIP RETURN. WE HAVE A DDB.

;ROUTINE TO FIND A TTY DDB WHICH IS ATTACHED TO, I.E.
;CONTROLLING, A PARTICULAR JOB NUMBER.
;
;CALLED AT COMMAND LEVEL BY ATTACH COMMAND, AND AT UUO LEVEL
;BY REFERENCES TO DEVICE "TTY" OR TTCALLS, ETC.
;
;CALL:	MOVE J,JOB NUMBER DESIRED
;	PUSHJ P,TTYSRC
;	  ERROR RETURN.	;NOT FOUND. AC'S U,F,S NOT GUARANTEED
;	NORMAL RETURN	;U, S AND F SET UP. NOTE THAT THIS DOES
;			;!NOT! IMPLY THAT ANYONE IS ATTACHED. THAT IS,
;			; U MAY CONTAIN A ZERO
;
;			;CLOBBERS T1

TTYSRC::JUMPLE	J,CPOPJ##	;NOBODY CONTROLS JOB ZERO. YOU ARE CONFUSED.
	HRRZ	F,TTYTAB##(J)	;GET CONTROLLING TTY DDB ADDRESS
	JUMPE	F,CPOPJ##	;RETURN IF NONE
	MOVE	T1,DEVMOD(F)	;GET DEVICE BITS FROM DDB
	TLNN	T1,TTYATC	;IS THIS THE CONTROLLING TTY?
	POPJ	P,0		;NO. IT WAS A SLAVE OR SOMETHING.
	HRRZ	U,DDBLDB(F)	;YES. GET THE LDB LINK (MAY BE 0)
	MOVE	S,DEVIOS(F)	;AND I/O STATUS WORD
	JRST	CPOPJ1##	;GIVE SUCCESS RETURN.
;ROUTINE CALLED WHEN DEVSRC CAN'T FIND DEVICE XXX (IN T1), AND
; IT WANTS TO SEE IF IT IS A PHYSICAL TTY. GETDDB CHECKS NAME,
; AND IF IT SHOULD BE A TTY, LOOKS FOR ITS DDB, OR MAKES ONE.
;
;CALL:	MOVE J,JOBNUMBER
;	MOVE T1,SIXBIT DEVICE NAME, ALLEGEDLY A PHYSICAL TTY NAME
;	PUSHJ P,GETDDB
;	  ERROR RETURN, NOT A TTY OR THERE ARE NO DDB'S AVAILABLE.
;	OK RETURN. IT IS A TTY, AND F AND U ARE NOW SET TO IT.
;RESPECTS T1 ON THE OK RETURN ONLY
;
;CALLED FROM DEVSRC, SO MAY BE AT UUO OR CLOCK LEVEL

GETDDB::
IFN FTMP,<
	PUSHJ	P,INTLVL##	;IF AT UUO LEVEL
	  PUSHJ	P,ONCPU0##	;AVOID RACES WITH COMCON
>
	PUSHJ	P,TTYPHY	;LOOK FOR THIS PHYSICAL NAME
	  POPJ	P,0		;IT ISNT A TTY
	JUMPN	F,GETDB5	;IS THERE A DDB ALREADY?
				;IF SO, SOMEONE HAS CALLED GETDDB WHO
				; COULD HAVE CALLED DEVSRC.
	PUSHJ	P,CHKFLN	;CHECK FOR LEGAL ACCESS TO FRCLIN
	PUSHJ	P,DDBSRC	;NO. NEED A NEW DDB. TRY TO GET ONE.
	  POPJ	P,0		;NONE AVAILABLE. FAIL RETURN
	HRRM	F,LDBDDB(U)	;SUCCESS. SET LINKS TO AND FROM DDB
	HRRM	U,DDBLDB(F)	; AND LINE DATA BLOCK.
	PUSHJ	P,SCNNAM	;FILL IN REAL NAME AND PUNIT
IFN FTNET,<PUSHJ P,SETSTA>	;PUT STA # IN DDB
GETDB5:	MOVE	T1,DEVNAM(F)	;RESTORE REAL NAME TO T1
	JRST	CPOPJ1##	;AND GIVE SUCCESSFUL RETURN FROM GETDDB


;ROUTINE TO CHECK FOR LEGAL ACCESS TO FRCLIN.
;CALL:	MOVE	U,LDB ADDRESS
;	PUSHJ	P,CHKFLN
;	  RETURN HERE IF NOT FRCLIN OR LEGAL ACCESS
;	  RETURN HERE IF ACCESS NOT LEGAL
;DESTROYS T1

CHKFLN:	LDB	T1,LDPLNO	;GET LINE NUMBER
	CAIE	T1,FRCLIN##	;IS IT FRCLIN?
	POPJ	P,		;NO, GIVE OK RETURN
	PUSHJ	P,SAVT##	;SAVE T1-T4 FOR SAFETY
	MOVSI	T1,JP.POK	;MUST HAVE POKE PRIVILEGE OR BE
	PJRST	PRVBIT##	;BE LOGGED INTO [1,2] OR JACCT
;SUBROUTINE TO PUT PHYSICAL NAME INTO T2 FOR U WHOSE LDB IS IN U
;EVEN THOUGH THERE MAY BE NOTHING IN F OR LDBDDB

TTYNAM::PUSH	P,[SIXBIT /CTY/];SEE IF CTY
	MOVEI	T1,LDRCTY
	TDNE	T1,LDBDCH(U)
	JRST	T2POPJ##	;YES.
	LDB	T1,LDPLNO
	MOVSI	T3,'TTY'	;NO. CHANGE TO TTY
	MOVEM	T3,0(P)		;ON STACK
	MOVSI	T3,(POINT 6,0,17) ;SETUP SIXBIT BYTE POINTER TO
	HRRI	T3,0(P)		;NAME ON THE STACK
	PUSHJ	P,SCNNMR	;AND CALL SAME ROUTINE AS SCNNAM DOES
	PJRST	T2POPJ##	;PUT ANSWER IN T2
				;AND RETURN FROM TTYNAM
;SUBROUTINE TO FIND LDB FOR A PHYSICAL NAME, IF ITS A TTY
;AND LOAD F WITH LINKED DATA BLOCK, IF ANY, BUT DON'T MAKE ONE IF NONE YET
;SKIP RETURN IF ITS A TTY


TTYPHX:	PUSHJ	P,TSTOPR##	;SEE IF OPR AND FUDGE T1
	PUSHJ	P,SAVE2##
	PUSH	P,T1		;SAVE NAME
	MOVE	P1,BOOTCT##
	CAMN	T1,[SIXBIT /CTY/] ;IS CTY WANTED?
	JRST	TTYPH1		;YES. GO USE TCONLN
	HLLZ	P1,T1		;GET FIRST THREE CHARACTERS
	CAMN	P1,[SIXBIT /TTY/] ;ARE THEY TTY?
	TRNN	T1,770000	;AND ALSO IS FOURTH CHAR NON-BLANK?
	PJRST	TPOPJ##		;NO. NOT A LEGAL NAME.
	MOVSI	P2,(<POINT 6,0(P),17>)	;POINTER TO READ CHARS
	MOVEI	P1,0		;INITIALIZE LINE TO 0
TTYPH4:	ILDB	T1,P2		;GET A SIXBIT CHARACTER FROM NAME
	JUMPE	T1,TTYPH2	;JUMP IF END OF NAME.
	TRC	T1,"0"-40	;CONVERT SIXBIT TO BINARY
	CAILE	T1,7		;IS IT AN OCTAL DIGIT?
	JRST	TPOPJ##		;NO. BAD CHAR IN NAME
	ASH	P1,3		;MULTIPLY BY 8
	ADDI	P1,0(T1)	;ADD IN THIS DIGIT
	TLNE	P2,770000	;CHECK FOR MORE DIGITS
	JRST	TTYPH4		;LOOP FOR MORE DIGITS
TTYPH2:	CAMLE	P1,P3		;IS IT A LEGAL HARDWARE LINE #?
	JRST	TPOPJ##		;NO. TOO BAD.
TTYPH1:	HRRZ	U,LINTAB##(P1)	;GET LINE DATA BLOCK ADDRESS
	HRRZ	F,LDBDDB(U)	;GET ATTACHED DDB, IF ANY.
	JRST	TPOPJ1##	;GOOD RETURN

TTYPHY::PUSH	P,P3		;SET UP FOR PHYSICAL ONLY
	MOVEI	P3,TCONLN##
TTYPHZ:	PUSHJ	P,TTYPHX	;CALL COMMON SUBROUTINE
	  SOS	-1(P)		;REMEMBER NON-SKIP RETURN
	POP	P,P3		;BY PROPAGATING IT
	JRST	CPOPJ1##

TTYALL::PUSH	P,P3		;TRY ALLL-PHYSICAL & VIRTUAL
	MOVEI	P3,TTPLEN##-1
	JRST	TTYPHZ
;SUBROUTINE TO FIND TTY FOR A JOB IN J (TTYFND) OR FOR
; CURRENT JOB (TTYFNU)
;RETURN WITH F AND U SET UP.
;GOES TO ERROR IF NO TTYDDB FOR THE JOB.


TTYFNU::MOVE	J,.CPJOB##	;GET CURRENT UUO LEVEL JOB NUMBER
TTYFND::PUSHJ	P,TTYSRC	;FIND THE JOB'S TTY DDB, ALSO U AND S
	  STOPCD CPOPJ##,DEBUG,NDJ,	;++NO DDB FOR JOB
TTYFNX:	POPJ	P,0		;SUCCESS. RETURN.

;SUBROUTINE TTYFUW (TELETYPE FIND FOR CURRENT USER AND WAIT), TO
;FIND CURRENT USER'S TTY AND WAIT FOR IT TO COME OUT OF OUTPUT
;WAIT, AND BE ATTACHED.
;SUBROUTINE TOWAIT, TO WAIT FOR TYPEOUT ACTIVITY TO (NEARLY) COMPLETE,
;IF NECESSARY.


TTYFUW::PUSHJ	P,TTYFNU	;FIND USER'S TTY
	PUSHJ	P,CKATTO	;CHECK THAT IT'S ATTACH. WAIT IF NOT.
IFN FTMIC,<			;IF MIC
	MOVE	T1,LDBMIC(U)
	TLNE	T1,LDLRSP!LDLRSY
	POPJ	P,0		;IF HE WANTS RESPONSE STUFF DO NOT TO
> ;END OF IF MIC
;ROUTINE TO WAIT FOR NEARLY EMPTY OUTPUT BUFFER. CALL ONLY AT UUO LEVEL
TOWAIT:	MOVE	S,[XWD	TTYOUW+IO+IOW,IOACT]	;SET ACTIVE & WAITING FIRST TO AVOID COMPLETION
	IORM	S,DEVIOS(F)	;BETWEEN TEST FOR COMPLETION & IOACT SET
	MOVE	T1,LDBTOC(U)	;GET COUNT OF TYPE-OUT CHARACTERS WAITING.
	CAIL	T1,10		;OVER 7?
	JRST	TOWAT2		;YES. HAVE TO WAIT
	ANDCAB	S,DEVIOS(F)	;NO. NOT WAITING, SO TURN OFF BITS
	POPJ	P,		;& RETURN
TOWAT1:	MOVE	S,[XWD TTYOUW+IO,IOACT]	;FLAG OUTPUT WAIT ACTIVITY
TOWAT2:	IORB	S,DEVIOS(F)	;IN THE DEVICE DATA BLOCK
	PUSHJ	P,PTSTRT	;WAKE UP SUBJOB, IF ANY
	PUSHJ	P,WSYNC##	;WAIT FOR IO TO COMPLETE
	HRRZ	U,DDBLDB(F)	;SET UP LDB IN CASE DETACH/ATTACHAPPENED WHILE WAITING
	JUMPE	U,[MOVE   U,DEVMOD(F)	;LDB PTR GONE, GET STATUS WORD
		   TLNE   U,TTYATC	;WAS THIS THE CONTROLLING TTY?
		   JRST   TTYFUW	;YES, GO LOOK FOR IT
		   MOVSI  S,TTYOUW+IO+IOW	;GET IO BITS
		   ANDCAB S,DEVIOS(F)		;AND CLEAR THEM
		   SETZ   U,		;NOTE NO TTY FOR THE DDB
		   POPJ   P,]		;RETURN WITH IODERR SET
	POPJ	P,		;AND RETURN


PTSTRT:	JUMPE	U,CPOPJ##	;IN CASE U NOT SET UP
	MOVEI	T1,LDRPTY	;GET PTY BIT
	TDNE	T1,LDBDCH(U)	;IS THIS ONE
	PJRST	PTYPE##		;YES, WAKE UP CONTROLLER
	POPJ	P,		;NO, RETURN
;SUBROUTINE TTYERP TO FIND TTY DDB FOR A MONITOR ERROR MESSAGE.
;CALL WITH J SET TO JOB NUMBER TO BE TYPED AT.
;IF JOB IS ZERO, OR IF DESIRED JOB IS DETACHED, TTYERP RETURNS
;WITH U SET TO OPERATOR'S CONSOLE, AND F SET FROM IT,
;BUT OF COURSE THAT DDB MAY BE ZERO, SINCE MAY BE NO JOB AT OPR.


TTYERP::PUSHJ	P,TTYSRC	;FIND THE TTY DDB IF POSSIBLE
	  JRST TTYERO		;NONE THERE. MAYBE JOB 0. GO FIND OPR
	JUMPN	U,CPOPJ1##	;SKIP RETURN TO SIGNAL LDB FOUND
TTYERO:	SKIPN	U,OPRLDB##	;GET OPERATOR LINE FROM ONCE
	STOPCD	CPOPJ##,DEBUG,NOT,	;++NO OPR TTY
	HRRZ	F,LDBDDB(U)	;GET DDB ADR, IF ANY.
TTYERX:	POPJ	P,0		;AND RETURN FROM TTYERP


;SUBROUTINES TO SET UP LINE AND MAKE SURE ATTACHED.
;CALL WITH DDB SET UP, FROM UUO LEVEL ONLY.
;RETURN WHEN ATTACHED AND AT USER LEVEL, WITH LINE SET UP.

;ONE ROUTINE FOR INPUT, ONE FOR OUTPUT, ONE FOR OUTPUT AND USER LEVEL

CKATTI:
IFN FTRSP,<PUSHJ P,RSPTIR##>	;RECORD RESPONSE SATISFIED BY TTY INPUT UUO
CKATT0:	MOVSI	S,IO		;INDICATE INPUT
	ANDCAB	S,DEVIOS(F)	;SET UP STATUS WORD
	HRRZ	U,DDBLDB(F)	;GET LINE BLOCK ADDR
	JUMPN	U,CKATI1	;IF THERE, GO ON
CKATIW:	MOVSI	S,IO+TTYOUW	;MUST WAIT FOR ATTACH
	ANDCAM	S,DEVIOS(F)	;CLEAR DIRECTION BIT
	MOVEI	S,IOACT		;AND SET WAIT BIT FOR INPUT
	IORB	S,DEVIOS(F)	; ..
	PUSHJ	P,WSYNC##	;WAIT FOR ATTACH
	JRST	CKATT0		;GET LINE SET UP AND RETURN.

CKATI1:	MOVE	T1,DEVMOD(F)	;SEE IF TTY IS CONTROLLING JOB.
	TLNE	T1,TTYATC
	JRST	CKATI2		;YES.
	MOVSI	T1,LDLCOM	;NO. MAKE IT BE
	ANDCAM	T1,LDBDCH(U)	;AT USER LEVEL
CKATI2:	HLL	U,LDBDCH(U)	;GET DEVICE BITS
	TLNE	U,LDLCOM	;AT COMMAND LEVEL?
	JRST	CKATIW		;YES. CAN'T DO INPUT.
	PUSHJ	P,TYIEAT	;NO. SKIP ANY COMMANDS
	PJRST	UUOLDB		;AND GO ADJUST LINE BITS.

CKATOU:	PUSHJ	P,CKATTO	;FIRST MAKE SURE A LINE ATTACHED TO DDB
	TLNN	U,LDLCOM	;IS LINE AT COMMAND LEVEL?
	POPJ	P,0		;NO. USER LEVEL. RETURN.
	MOVE	T1,DEVMOD(F)	;COMMAND LEVEL.  SEE IF CONTROLLER OR I/O DEVICE
	TLNN	T1,TTYATC	;..
	POPJ	P,0		;I/O DEVICE.  LET IT THROUGH.
	PUSHJ	P,TOWAT1	;CONTROLLER.  WAIT SO DON'T CLOBBER COMMANDS
	JRST	CKATOU		;THEN TRY AGAIN FOR USER LEVEL

CKATTO:	MOVSI	S,IO		;INDICATE OUTPUT
	IORB	S,DEVIOS(F)	;SET UP STATUS WORD
	HRRZ	U,DDBLDB(F)	;GET LINE ADDR IF ANY
	JUMPN	U,CKATO1	;IF HAVE ONE, SEE IF TOP LEVEL
CKATOW:	PUSHJ	P,TOWAT1	;WAIT FOR OUTPUT DONE. (WHICH
				; IS FORCED ON ATTACH)
	JRST	CKATTO		;AND SET UP LINE, TO RETURN.
CKATO1:	HLL	U,LDBDCH(U)	;GET LINE DESCRIPTOR BITS
;	PJRST UUOLDB		;FALL INTO UUOLDB

UUOLDB::MOVEI	T1,0		;MAKE LDB AGREE WITH S
	MOVE	T2,LDBDCH(U)	;REMEMBER OLD CHARACTERISTICS
	TRNE	S,IOSTEC	;TRUTH-IN-ECHOING SET?
	TLO	T1,LDLDLR	; YES
	TRNE	S,IOSFCS	;FULL-CHARACTER-SET SET?
	TLO	T1,LDLFCS	; YES
	TRNE	S,PIMMOD	;IS THIS PACKED IMAGE MODE?
	TLOA	T1,LDLPIM	; YES, SET FLAG IN LDB (AND FORCE NO ECHO)
	TRNE	S,IOSNEC	;NO ECHO BY PROGRAM?
	TLO	T1,LDLNEC	; YES
;THIS SHOULD NO LONGER BE NEEDED, ONLY TT?CHK SHOULD SET/CLEAR IT
;	TRNE	S,IOSBKA	;SINGLE CHARACTER MODE?
;	TLO	T1,LDLBKA	; YES
	IORM	T1,LDBDCH(U)	;SET THOSE NEEDING SETTING
;	TLC	T1,LDLNEC+LDLFCS+LDLDLR+LDLBKA+LDLPIM
	TLC	T1,LDLNEC+LDLFCS+LDLDLR+LDLPIM
	ANDCAB	T1,LDBDCH(U)	;AND CLEAR THE OTHERS

IFN FTCIMP,<			;[arpa]
	TRNN	T2,LDRIMP	;[arpa] IS THIS AN IMP?
	  JRST	UUOLD2		;[arpa] NO, DON'T MESS
	PUSH	P,T3		;[arpa] YES - SAVE ANOTHER AC
	MOVE	T3,T1		;[arpa] SEE IF LDLNEC CHANGED (1 AFTER XOR)
	XOR	T3,T2		;[arpa] XOR IN OLD BITS
	TLNN	T3,LDLNEC	;[arpa]
	  JRST	UUOLD1		;[arpa] ZERO, DIDN'T CHANGE
	PUSH	P,T2		;[arpa] SAVE SOME AC'S
	PUSH	P,T1		;[arpa]
	MOVEI	T3,400+.TNIAC##	;[arpa]
	PUSHJ	P,CCTYO9	;[arpa] SEND TELNET CONTROL/ESCAPE
	MOVE	T3,LDBDCH(U)	;[arpa] GET CURRENT STATE OF NO-ECHO
	TLNN	T3,LDLNEC	;[arpa] IF ON, TRY TO DO IT, BUT...
	  SKIPA	T3,[400+.TNWNT##] ;[arpa] (ON: LET THE OTHER GUY DO IT)
	MOVEI	T3,400+.TNWIL##	;[arpa] (OFF:) ...DON'T SAY THAT WE WILL DO IT
	PUSHJ	P,CCTYO9	;[arpa] SEND WHATEVER DECIDED ON
	MOVEI	T3,400+.TOECH##	;[arpa] FOLLOW WITH ECHO NEGOTIATION CODE
	PUSHJ	P,CCTYO9	;[arpa] AND SEND THAT TOO
	POP	P,T1		;[arpa]
	POP	P,T2		;[arpa] RESCUE OPERATIONS
UUOLD1:	POP	P,T3		;[arpa] RESCUE THE STACK
UUOLD2:				;[arpa]
> ;[arpa] END FTCIMP
	CAME	T2,T1		;DON'T SEND STATUS IF NO CHANGE
	PJRST	SETCHP		;NOTE THAT TERMINAL CHARACTERISTICS CHANGED
	POPJ	P,		;NO CHANGE
;HERE FROM UUOCON WHEN A TTY HAS BEEN INITED.

TTYOPN::HRRZ	U,DDBLDB(F)	;GET LDB ADDRESS
	JUMPE	U,TPOPJ1##	;FORGET IT IF DETACHED
	MOVSI	T2,LDLCOM	;GET COMMAND LEVEL BIT
	MOVSI	T1,TTYATC	;IS TTY CONTROLLING THE JOB?
	TDNN	T1,DEVMOD(F)	;OR IS IT AN I/O DEVICE?
	ANDCAM	T2,LDBDCH(U)	;I/O PUT IT AT USER LEVEL
	PUSHJ	P,UUOLDB	;SETUP THE LDB FROM S
	PUSHJ	P,SETCHP	;MAKE SURE THE FRONT END KNOWS ABOUT THIS
	JRST	TPOPJ1##	;AND RETURN
;TWAITI  --  WAIT FOR INPUT (CHARACTER OR LINE MODE)

TWAITI:	TRNE	S,IOSBKA	;BREAK ON ALL CHARACTERS?
	JRST	TWAITC		;YES, WAIT FOR A SINGLE CHARACTER
				;FALL INTO TWAITL (EVEN FOR IMAGE MODES)

;TWAITL  --  WAIT FOR AN INPUT LINE

TWAITL:
IFN FTTVP,<
	SKIPG	LDBTOC(U)	;IF NO OUTPUT IN PROGRESS,
	PUSHJ	P,CLRPCT	;RESET THE "STOP" LINE COUNTER
> ;END IFN FTTVP
	PUSHJ	P,CKATTI	;FIRST WAIT FOR ATTACH. SET DDB AND LINE
	PUSHJ	P,TTLCHK	;CHECK FOR A LINE BEING PRESENT
	  JRST	TWATLK		;BE SURE
	POPJ	P,		;LINE PRESENT, RETURN

TWATL1:	PUSHJ	P,TIWAIT	;NO. GO WAIT FOR ONE.
	TRNE	S,IODERR	;GOT A ↑C?
	POPJ	P,		;YES, LINE PRESENT
	PUSHJ	P,CKATTI	;MAKE SURE DIDN'T DETACH DURING WAIT
	PUSHJ	P,TTLCHK
	  JRST	TWATLK
	POPJ	P,

TWATLK:	MOVE	S,[XWD IOW,IOACT]	;FLAG ACTIVE AND WAITING SO
	IORB	S,DEVIOS(F)	;INTERRUPT WILL NOT FIND HIM ACTIVE
	PUSHJ	P,TTLCHK	;BUT NOT WAITING.  THEN LOOK AGAIN
	  JRST	TWATL1		;NOTHING ARRIVED SINCE LAST TEST
	MOVE	S,[XWD IOW,IOACT]	;SOMETHING DID SNEAK IN!
	ANDCAB	S,DEVIOS(F)	;SO FORGET ABOUT WAITING
	POPJ	P,



;SUBROUTINE TO WAIT FOR SINGLE CHARACTER INPUT

TWAITC:
IFN FTTVP,<PUSHJ P,CLRPCT>	;CLEAR LINE COUNT FOR AUTO-PAGE MODE
	PUSHJ	P,CKATTI	;MAKE SURE ATTACHED
	PUSHJ	P,TTCCHK	;CHECK FOR A CHARACTER PRESENT
	  SKIPA			;NONE PRESENT, GO WAIT
	POPJ	P,0		;YES. RETURN
	MOVE	S,[XWD	IOW,IOACT]	;SET BOTH ON TO AVOID RACE WITH COMPLETION
	IORB	S,DEVIOS(F)	;SO NOT GO INTO TI WITH SOMETHING THERE
	PUSHJ	P,TIWAIT	;NO. GO WAIT FOR ONE
	TRNE	S,IODERR	;GOT A ↑C?
	POPJ	P,		;YES, THAT'S ENOUGH
	JRST	TWAITC		;MAKE SURE ONE THERE IN CASE OF ↑C
;TTICHK  --  CHECK IF ANY INPUT IS AVAILABLE, LINE OR CHARACTER MODE
;CALL IS:
;
;	PUSHJ	P,TTICHK
;	  NO INPUT AVAILABLE
;	INPUT IS AVAILABLE
;
;THE CALLER MUST SETUP U, F, AND S APPROPRIATELY (TTLCHK AND TTCCHK
;DON'T REQUIRE F AND S, BUT TTICHK DOES).
;
;TTLCHK IS THE ROUTINE THAT HANDLES REGULAR ASCII LINE MODE, AS
;AS THE IMAGE MODES, TTCCHK HANDLES ASCII CHARACTER MODE.

TTICHK:	TRNE	S,IOSBKA	;BREAK ON ALL CHARACTERS MODE?
	JRST	TTCCHK		;YES, LOOK FOR JUST A SINGLE CHARACTER
				;NO, FALL INTO TTLCHK (EVEN FOR IMAGE MODES)

;TTLCHK  --  CHECK IF AN INPUT "LINE" IS AVAILABLE

TTLCHK::MOVSI	T1,LDLBKA	;CLEAR BREAK ON ALL CHARACTERS BIT
	ANDCAM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
TTLCK2:	TRNN	F,-1		;DO WE REALLY HAVE A DDB?
	SETZ	S,		;NO DDB, NO I/O STATUS
	SKIPLE	T1,LDBTIC(U)	;ANY INPUTTABLE CHARACTERS?
	TRNN	S,I!PIMMOD	;YES, IMAGE MODE OF SOME SORT?
	SKIPLE	LDBBKC(U)	;LINE MODE, ANY LINES AVAILABLE?
	JRST	CPOPJ1##	;INPUT AVAILABLE
	CAIL	T1,↑D70		;NO LINES, GOT LOTS OF CHARACTERS?
	JRST	CPOPJ1##	;YES, CLOSE ENOUGH, WAKE UP USER
	TLNE	U,LDLIMI	;NO. IMAGE INPUT STATE?
	TLNN	S,FRCEND	;YES. ALSO TIMED OUT?
	PJRST	STRTDL		;ECHO ONE DEFERRED LINE IF NEEDED
	JRST	CPOPJ1##	;IMAGE TIME OUT, WAKE UP HIGHER-UPS

;TTCCHK  --  CHECK IF  AN ASCII CHARACTER IS AVAILABLE

TTCCHK:	MOVSI	T1,LDLBKA	;SET "BREAK ON ALL CHARACTERS" BIT
	IORM	T1,LDBDCH(U)	;IN LINE DATA BLOCK
	SKIPLE	LDBTIC(U)	;IS THERE A CHARACTER ALREADY?
	JRST	CPOPJ1##	;YES, SKIP RETURN
	PJRST	STRTDC		;NO, ECHO ONE DEFERRED CHARACTER IF NEEDED
;SUBROUTINE TIWAIT TO WAIT FOR SOME INPUT, AND SEND XON IF NEEDED.

TIWAIT:
IFN FTMIC,<			;IF MIC
	SKIPE	LDBMIC(U)	;MIC RUNNING FOR THIS LINE?
	PUSHJ	P,MICWAK	;YES, WAKE MIC IF NECESSARY
> ;END OF IF MIC
	MOVEI	T1,LDRPTY	;IS THIS LINE PTY-DRIVEN?
	TDNE	T1,LDBDCH(U)	;CHECK	IN THE LDB CHARACTERISTICS
	PUSHJ	P,PTYOW##	;YES. GO MARK THIS WAIT.
IFN FTCAFE,<IFN FT2741!FTNET,<	;IF WE SUPPORT 2741'S ON THE DC76
	PUSHJ	P,UNLKBD	;UNLOCK KEYBOARD
> ;END FT2741
> ;END FTCAFE
	MOVSI	S,IO+TTYOUW	;MARK DIRECTION AS INPUT.
	ANDCAB	S,DEVIOS(F)	;CLEAR IN CORE
	MOVEI	T1,IMGTIM	;TIMEOUT FOR IMAGE MODE
	TRNE	S,I		;TERMINAL IN IMAGE MODE?
	DPB	T1,LDPTIM	;YES. STORE TIMEOUT TIME
	PUSHJ	P,CHKXON	;SEND X-ON IF NEEDED
	JRST	WSYNC##		;WAIT FOR INPUT



;SUBROUTINE TO START DEFERRED ECHO
;CALL
;	MOVEI	T2,BIT (EITHER L1RDEL FOR LINE OR L1RDEC FOR CHARACTER)
;	PUSHJ	P,STRTDE
;	<ALWAYS RETURNS HERE>

STRTDC::MOVEI	T2,L1RDEC	;THE ALLOW-ONE-CHARACTER-TO-ECHO BIT
	TDNN	T2,LDBBYT(U)	;IS IT ALREADY SET, OR
	SKIPLE	LDBTIC(U)	;ARE ANY CHARACTERS AVAILABLE?
	POPJ	P,		;YES, DON'T ECHO ANY MORE
	JRST	STRTDE		;COMMON CODE

STRTDL::MOVEI	T2,L1RDEL	;THE ALLOW-ONE-LINE-TO-ECHO BIT
	TDNN	T2,LDBBYT(U)	;IS IT ALREADY SET, OR
	SKIPLE	LDBBKC(U)	;ARE ANY LINES AVAILABLE?
	POPJ	P,		;YES, DON'T ECHO ANY MORE

STRTDE::IORM	T2,LDBBYT(U)	;SET BIT ALLOWING LINE OR CHARACTER
	MOVEI	T2,L1RDEM	;GET DEFERRED ECHO MODE BIT
	TDNE	T2,LDBBYT(U)	;DEFERRED?
	SKIPG	LDBECC(U)	;AND INPUT WAITING?
	PJRST	CHKXON		;NOT DEFERRED, OR NO INPUT WAITING
				; MAKE SURE WE ARE ACCEPTING INPUT
	PJRST	TOPOKE		;GET OUTPUT STARTED
;ROUTINE TO CHECK IF AN XOFF HAS BEEN SENT OUT
;AND IF SO, TO SEND AN XON.
;CALLED BY:
;	PUSHJ	P,CHKXON
;	RETURN HERE ALWAYS (CLOBBERS T1,T3)


CHKXON::MOVSI	T1,LPLXOF	;IS PAGE MODE ENABLED?
	TDNN	T1,LDBPAG(U)	;GUARANTEE XON IF TALKING TO
				;ANOTHER COMPUTER
	POPJ	P,		;XON IS NOT NEEDED

CHKXN1:	MOVE	T1,LDBTIC(U)	;GET # OF INPUT CHARS
	ADD	T1,LDBECC(U)	;PLUS THOSE TO BE ECHOED
	CAILE	T1,↑D80		;TOO MANY?
	POPJ	P,		;YES, GO AWAY
	MOVSI	T1,LPLXOF	;CLEAR XOFF BIT
	ANDCAM	T1,LDBPAG(U)	;SO ONLY ONE XON IS SENT
	MOVE	T2,FLPXON	;GET POINTER TO XON
	PUSHJ	P,SETXNP	;NOTE THAT WE HAVE FILLERS
	PJRST	TOPOKE		;START TERMINAL MOVING
				;IFN FTTPAG

;ROUTINE TO GET DDB OUT OF TI WAIT IF NEEDED
;CALLED BY:
;	MOVE	J,JOB #
;	PUSHJ	P,CLRTI
;	RETURN	HERE
;RESPECTS	T1,T2
CLRTI::	PUSH	P,T1		;SAVE SOME AC'S
	PUSH	P,T2
	LDB	T1,PJBSTS##	;GET WAIT STATE CODE
	CAIE	T1,TIOWQ##	;IN TI WAIT?
	JRST	CLRTI1		;NO--EXIT
	PUSHJ	P,TTYSRC	;FIND TTY DDB
	  JRST	CLRTI1		;NO DDB?
	MOVE	T1,[IOW,,IOACT]
	ANDCAM	T1,DEVIOS(F)
CLRTI1:	POP	P,T2
	JRST	TPOPJ##

IFE FT2741,<
UNLKBD==CPOPJ##
>
IFN FT2741,<			; WITH 2741 SUPPORT
;SUBROUTINE TO UNLOCK 2741 KEYBOARD:
;CALL WITH:
;	MOVEI	U,ADDRESS-OF-LDB
;	PUSHJ	P,UNLKBD
;	RETURN HERE
UNLKBD:	MOVEI	T1,LDR2741	;SET UP 2741 BIT
	TDNE	T1,LDBDCH(U)	;...
	JRST	UNLKB1		;IF A 2741
	MOVEI	T1,L2RXON	;SET UP XON BIT
	TDNN	T1,LDBBY2(U)	;SKIP
	POPJ	P,		;IF NEITHER A 2741 OR XON SET
UNLKB1:	SKIPN	LDBBKC(U)	;DON'T GIVE UP IF HAVE BRK CHAR
	SKIPL	LDBDCH(U)	;SKIP IF NOT OUTPUT IN PROGRESS
	POPJ	P,0		;JUST RETURN
	PUSH	P,T2		;SAVE T2
	PUSH	P,T3		;AND T3
	MOVEI	T1,ISRLPC	;FUNCTION
	MOVEI	T3,<LPCUKB>B27	;SUBFUNCTION
	PUSHJ	P,@LDBISR(U)	;CALL D76INT (OR WHATEVER)
	POP	P,T3		;RESTORE T3
	PJRST	T2POPJ##	;RESTORE T2 AND RETURN
>;IFN FT2741



IFN FTMSGSER,<
;SUBROUTINE TO RETURN TTY OUTPUT FEASIBILITY FOR A MPX-CONTROLLED TTY
;CALL WITH F/ADDRESS OF TTY DDB
;RETURN WITH T1/0 IF NO OUTPUT OR 1 IF OK TO OUTPUT

TTYOFE::HRRZ	T2,DDBLDB(F)	;ADDRESS OF TTY LDB
	MOVE	T1,LDBTOC(T2)	;COUNT OF OUTPUT CHARACTERS STILL WAITING
	HLL	T1,LDBDCH	;FLAG BITS
	TDNE	T1,[LDLSTP+777740]  ;IF ↑S'ED OR MORE THAN 32 CHARACTERS
	TDZA	T1,T1		;SAY OUTPUT NOT FEASIBLE
	MOVEI	T1,1		;OTHERWISE GIVE GO AHEAD
	POPJ	P,		;RETURN TO MSGSER
> ;END IFN FTMSGSER
;ROUTINE TO PUT SIXBIT NAME IN DEVNAM(DDB), AND TO SET PUNIT.

;CALL:	SET DDB TO DEVICE DATA BLOCK TO RECEIVE THE NAME AND UNIT
;	SET LINE TO LINE DATA BLOCK WHERE LINE NUMBER WILL BE FOUND
;	AND SET OR CLEAR IMAGE BIT IN DEVMOD DEPENDING ON
;	WHETHER THIS LINE WILL BE PTY-DRIVEN OR NOT
;	PUSHJ P,SCNNAM
;	RETURN
;CLOBBERS T1 AND T3


SCNNAM:	PUSH	P,T2		;SAVE T2
	PUSHJ	P,TTYNAM	;BUILD NAME OF DEVICE
	MOVEM	T2,DEVNAM(F)	;STORE IN DDB
	POP	P,T2		;RESTORE T2
	LDB	T1,LDPLNO	;GET PHYSICAL LINE NUMBER
	DPB	T1,PUNIT##	;AND STORE IT IN THE DDB
	SETZM	DEVSTS(F)
	MOVEI	T3,<1←I>	;GET IMAGE MODE BIT.
	IORM	T3,DEVMOD(F)	;SET IT IN THE DDB
	MOVE	T1,LDBDCH(U)	;GET DEVICE BITS
	TRNE	T1,LDRPTY	;IS THIS A PTY?
	ANDCAM	T3,DEVMOD(F)	;YES. CLEAR THE BIT.
	POPJ	P,0		;RETURN FROM SCNNAM


;SUBSIDIARY ROUTINE TO DO RADIX PRINT TO CORE.

SCNNMR:	IDIVI	T1,10		;DEVICE NAMES ARE OCTAL
	HRLM	T1+1,0(P)	;STORE A DIGIT ON STACK
	SKIPE	T1		;NEED MORE DIGITS?
	PUSHJ	P,SCNNMR	;YES. GO MAKE THEM.
	HLRZ	T1,0(P)		;RETRIEVE A DIGIT FROM STACK
	ADDI	T1,"0"-40	;CONVERT TO SIXBIT
	IDPB	T1,T3		;STORE IN OBJECT WORD (DEVNAM)
	POPJ	P,0		;POP UP TO SCNNMR OR BACK TO SCNNAM
IFN FTNET,<

;ROUTINE TO LOCATE A NEW TTY DDB

SETSTA:	PUSHJ	P,FNDSTA	;FIND STATION
	DPB	T1,PDVSTA##	;PUT STA # IN DEVICE LOC FIELD
	POPJ	P,		;RETURN

FNDSTA::MOVE	T1,LDBDCH(U)	;GET TTY BITS
	TRNN	T1,LDRPTY	;TERMINAL A PTY LINE?
	JRST	DDBRL		;NO - BRANCH FOR REAL TERMINAL
	LDB	T1,LDPLNO	;YES, GET LINE NUMBER ONLY
	SUBI	T1,PTYOFS##	;DECREMENT TO PTY LINE NUMBER
	PUSH	P,F		;SAVE TTY DDB FOR A SECOND
	MOVE	F,PTYTAB##(T1)	;GET PTY DDB
	LDB	T1,PDVSTA##	;GET LOCATION OF PTY
	JRST	FPOPJ##		;RESTORE TTY DDB AND RETURN TO CALLER

DDBRL:	TRNN	T1,LDRREM	;REMOTE STATION TERMINAL?
	JRST	DDBRL1		;NO, MUST BE A LOCAL TERMINAL
	LDB	T1,LDPRNN	;YES, GET THE REMOTE NODE NUMBER
	JUMPE	T1,DDBRL1	;LOCAL(?)
	POPJ	P,		;RETURN.

DDBRL1:	MOVEI	T1,LOCSTA##	;LOCAL STATION
	POPJ	P,		;RETURN


>
;ROUTINE TO ESTABLISH DEVICE OPR IF POSSIBLE
;CALL:	MOVE	T1,DEVICE NAME
;	PUSHJ	P,STDOPR
;RETURN CPOPJ IF ILLEGAL
;SKIP RETURN WITH DEVICE CHANGED
STDOPR::PUSHJ	P,TTYPHY	;LOOK FOR THIS PHYSICAL NAME
	  POPJ	P,		;FAILED IF NOT POSSIBLE
	HRRZM	U,OPRLDB##	;SAVE NEW LDB ADDRESS
	MOVEM	T1,DEVOPR##	;SAVE NEW NAME
	JRST	NETOPR##	;TELL NETWORK THAT OPR CHANGED
	SUBTTL	ROUTINES FOR PTY

;PTYPUT IS CALLED FROM PTYSER TO PLACE A CHARACTER IN A TERMINAL INPUT
;BUFFER AS THOUGH THE TERMINAL HAD BEEN TYPED ON. NO ECHOING IS ALLOWED,
;THOUGH AND THIS ROUTINE IS A SIMPLIFIED VERSION OF RECINT AND
;XMTECH, TO MAKE THE CHARACTERS VISIBLE TO THE CONTROLLED JOB WITHOUT ECHOING
;CALL
;	MOVE	T3,CHAR
;	MOVE	T1,CHAR BITS FROM SPCHEK
;	PUSHJ	P,PTYPUT
;	  ERROR	RETURN
;	  NORMAL RETURN

CNTRLO==17
PTYPUT::PUSHJ	P,SAVE1##	;PRESERVE P1
	MOVSI	P1,LDLFSP	;THE FULL-SCNSER-SERVICE BIT
	TDNE	P1,LDBTTW(U)	;IS THIS PTY BEING A TTY?
	JRST	PTYPT1		;YES, LET SCNSER DO CHARACTER HANDLING
	TLNE	T1,CHALT	;POSSIBLE ALTMODE?
	PUSHJ	P,RIALTO	;YES, CONVERT IF WANTED
	MOVE	P1,T1		;SAVE BITS IN P1
ifn ftcimp,<	;[arpa] incase some clown is cross patched out over a PTY.
	SKIPN	f,LDBIMP(U)	;[arpa] CROSSPATCHED TO IMP?
	  JRST	PtyNCP		;[arpa] NO.
	pushj	p,RecQuo##	;[arpa] is it something the NET wants to know?
	  pjrst	cpopj1##	;[arpa] yes, thank you.  we handled it.
				;[arpa] else not ours.  continue looking.
PtyNCP:				;[arpa] not cross patched
> ;[arpa] end of ifn FTCIMP
	CAIN	T3,CNTRLO
	PJRST	FLPCNO
IFN FTMIC,<			;IF MIC
	SKIPE	LDBMIC(U)
	CAIE	T3,1		;CONTROL A COUNTS AS ↑C TO MIC
> ;END OF IF MIC
	CAIN	T3,3		;CONTROL C?
	JRST	PTYCC		;YES. SPECIAL CHECKING
IFN FTWATCH,<
	CAIN	T3,"T"-100
	JRST	PTYCT
PTYINA:>
	MOVSI	T2,L2LCCS	;NOT CONTROL C, SO
	ANDCAM	T2,LDBBY2(U)	;CLEAR SYNC BIT
IFN FTMIC,<			;IF MIC
	SKIPE	T2,LDBMIC(U)
	JRST	PTYMCK
> ;END OF IF MIC


;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

PTYPT1:	MOVE	T2,LDBTIC(U)	;IS THIS LINE ALREADY FULL?
	CAIG	T2,↑D200	; ..
	SKIPG	TTFREN##	;OR LISTS EXHAUSTED?
	POPJ	P,0		;YES. DISCARD CHAR
	SKIPN	TTFTAK		;ANY FREELIST
	POPJ	P,0		;NO--PUNT
	AOS	(P)		;GOING TO GIVE GOOD RETURN NOW
	MOVSI	T2,LDLFSP	;THE FULL-SCNSER-PTY BIT
	TDNE	T2,LDBTTW(U)	;IS THIS UNDER FULL SCNSER CONTROL?
	PJRST	RECPTY		;YES, ENTER AT THE TOP
IFN FTMIC,<			;IF MIC
	MOVE	T1,P1		;SETUP CHARACTER BITS FOR MICECH
	SKIPE	LDBMIC(U)
	PUSHJ	P,MICECH	;SAY COL1 TO MIC
> ;END OF IF MIC
	SCNOFF			;NO INTERRUPTION
	STCHK	T3,LDBTIP(U)	;STORE CHARACTER
	TLNE	P1,CHBRK	;IS THIS A BREAK CHARACTER?
	PUSHJ	P,SETBKU	;YES, STORE LAST BREAK POINTER
	LDCHK	T3,LDBECT(U)	;TAKE CHARACTER NEEDING ECHO
	TLNE	P1,CHBRK	;BREAK CHAR?
	AOS	LDBBKC(U)	;YES. COUNT BREAKS
	AOS	T2,LDBTIC(U)	;ADVANCE TYPEIN COUNT
	SCNON			;ALLOW INTERRUPTS AGAIN
	TLNE	U,LDLBKA	;TERMINAL IN BREAK-ON-ALL MODE?
	PUSHJ	P,RCVWKQ	;YES. WAKE JOB IF WAITING
	CAIG	T2,TTIBRK	;ENOUGH TO WAKE ON?
	TLNE	P1,CHBRK	;OR A BREAK CHARACTER?
	PUSHJ	P,ECHBRK	;YES. WAKE THE JOB
	POPJ	P,		;SUCCESSFUL RETURN TO PTYSER
;MORE OF PTYPUT. SPECIAL CODE FOR CONTROL C

PTYCC:
IFN FTMIC,<			;IF MIC
	SKIPE	T1,LDBMIC(U)
	PUSHJ	P,MICPRC
> ;END OF IF MIC
	PUSHJ	P,RIDLN		;YES. DO SO.
	MOVSI	T1,L2LCCS	;SECOND CONTROL C?
	TDNE	T1,LDBBY2(U)	; ..
	PUSHJ	P,CNCCHK	;YES. FORCE CONTROL C IF POSSIBLE
	  JRST	PTYCC1		;NOT SECOND--GO SET BIT
	  JRST	PTYCC4		;NO. (JACCT) JUST PASS THE CHARACTER
	PUSHJ	P,TSETBI	;YES. CLEAR BUFFERS
	PUSHJ	P,TSETBO	; ..
	JRST	CPOPJ1##

PTYCC4:	PUSHJ	P,TTHALT	;FORCE .HALT COMMAND
PTYCC1:	MOVSI	T1,L2LCCS	;SET "↑C LAST IN" BIT
	IORM	T1,LDBBY2(U)	;SET BIT FOR NEXT TIME
	JRST	PTYPT1		;AND GO STORE CONTROL C IN INPUT BUFFER


;HERE ON ↑O TO PTY

FLPCNO:	MOVEI	T1,LDROSU	;FLIP THE ↑O BIT WHEN PTY OR REMOTE
	XORM	T1,LDBDCH(U)	;SENDS ↑O
	PUSHJ	P,TSETBO	;CLEAR THE OUTPUT BUFFER
	PJRST	XMTWAK		;WAKE JOB IF IN OUTPUT WAIT
IFN FTWATCH,<
PTYCT:	PUSHJ	P,DOCTLT
	  JRST	PTYINA
	  JRST	TTFRC1
	JRST	CPOPJ1##
>
;SUBROUTINE TO SET DEFAULT TERMINAL CHARACTERSTICS
;CALLING SEQUENCE:
;	MOVEI	T1,TERMINAL TYPE
;	MOVE	U,ADDRESS OF THE LDB
;	PUSHJ	P,SETTTC
;	ALWAYS RETURN HERE

SETTTC::MOVE	T2,T1
	JUMPGE	T1,SETTT1	;CUSTOMER DEFINED TYPE ?
	MOVNS	T2		;YES
	TRO	T2,100		;CUSTOMER TYPES ARE 101-177
SETTT1:	DPB	T2,LDPTTT	;STORE TERMINAL TYPE
	LSH	T1,1		;2 WORDS PER ENTRY
	LDB	T2,TTPWID	;WIDTH
	DPB	T2,LDPWID	;STORE THAT
	LDB	T2,TTPPSZ	;PAGE SIZE
	DPB	T2,LDPPSZ	;STORE THAT
	LDB	T2,TTPFLC	;FILLER CLASS
	DPB	T2,LDPFLC	;STORE THAT
	LDB	T2,TTPFRM	;FORM FEED
	DPB	T2,LDPFRM	;STORE THAT
	LDB	T2,TTPTAB	;TABS
	DPB	T2,LDPTAB	;STORE THAT
	LDB	T2,TTPLCT	;LOWER CASE
	DPB	T2,LDPLCT	;STORE THAT
	LDB	T2,TTPALT	;ALTMODE CONVERSION
	DPB	T2,LDPALT	;STORE THAT
	LDB	T2,TTPDIS	;GET DISPLAY SETTING
	DPB	T2,LDPDIS	;STORE THAT
	POPJ	P,		;RETURN
;TWO SUBROUTINES TO INITIALIZE THE LDB. LDBCLR SETS UP THE BITS FROM
;INITIAL STATE FOUND IN LINTAB, THEN FALLS INTO LDBINI. LDBINI JUST
;CLEARS AS REQUIRED ON 140 RESTART.
;BOTH SHOULD BE CALLED WITH LINE SET UP.

LDBCLR::LDB	T1,LDPLNO	;GET LINE NUMBER
	LDB	T1,LNPVRG	;GET VIRGIN-STATE BITS FROM LINTAB
	TRZ	T1,4		;CLEAR INITIA BIT
	DPB	T1,LDPVR2	;STORE THEM AROUND THE LDB
	LSH	T1,-5		; ..
	DPB	T1,LDPVR1	; ..
	LSH	T1,-6		; ..
	DPB	T1,LDPFLC	;LAST IS THE FILLER CLASS
	MOVSI	T1,LDLFSP	;INITIALLY UNKNOWN TERMINAL TYPE
	ANDM	T1,LDBTTW(U)
IFN FT2741,<
	LDB	T1,LDPSPD
	MOVEI	T2,LDR2741
	CAIN	T1,104
	IORM	T2,LDBDCH(U)
>;IFN FT2741
LDBINI::MOVSI	T1,LDBCMR+LDBCMK;CLEAR COMMAND REQUEST BITS
	ANDCAM	T1,LDBDDB(U)	;IN LINE DATA BLOCK
	MOVE	T1,[LDIBCM]
	ANDCAM	T1,LDBBYT(U)	;CLEAR MOST BYTES
	MOVE	T1,LDIDCM	;CLEAR DEVICE CHARACTERISTICS
	ANDCAM	T1,LDBDCH(U)	; AS APPROPRIATE
	MOVSI	T1,LDLIDL	;GET THE IDLE BIT
	IORM	T1,LDBDCH(U)	;WHICH SHOULD NORMALLY BE SET
IFN FTCIMP,<			;[arpa]
	SETZM	LDBIMP(U)	;[arpa] CLEAR IMP RELATED WORDS
	SETZM	LDBQUO(U)	;[arpa]
>				;[arpa]
	MOVEI	T1,↑D72		;INITIAL VALUE OF TERMINAL WIDTH
	DPB	T1,LDPWID	;STORE IN LDB
	MOVSI	T1,L2LCLR	;CLEAR NECESSARY BITS IN LDBBY2
	ANDCAM	T1,LDBBY2(U)	; ..
	LDB	T3,LDPLNO	;COPY LINE NUMBER
	MOVSI	T1,LDLCOM+LDLLCT;ASSUME AT COMMAND LEVEL AND UPPER CASE
IFN FTD10H,<			;CODE FOR 2741 ON DC10H
	HLRZ	T2,LINTAB##(T3)	;GET BITS FROM LINTAB
	TRNN	T2,TTVDIS##	;IS IT A DISPLAY LINE
				; WHICH INDICATES ITS A DC10H LINE?
	  JRST	.+4		;NO
	MOVSI	T2,LILCFE	;SET CLEVER BIT
	IORM	T2,LDBISR(U)	; IN THE LDB.
	TRO	T1,LDR2741	;ALSO TELL LDB ITS A 2741
>;END IFN FTD10H
IFN FTKS10,<
	MOVSI	T2,LILCFE	;CLEVER BIT
	CAIGE	T3,M.DZNL##	;IS THIS A DZ11 LINE ?
	IORM	T2,LDBISR(U)	;IS DZ11 LINE
>;IFN FTKS10

;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE

IFN FTCIMP,<				;[arpa]
	CAIL	T3,ITYFST##		;[arpa] IS THIS AN ITY?
	 CAIL	T3,ITYFST##+ITYN##	;[arpa]
	  JRST	LDBIMI			;[arpa] NO
	TLZ	T1,LDLLCT		;[arpa] YES, ALWAYS LOWER CASE
	TRO	T1,LDRIMP		;[arpa] always make it an IMP
LDBIMI:					;[arpa]
>					;[arpa]
	CAMN	T3,BOOTCT##	;THIS THE CTY
	TRO	T1,LDRCTY	;YES--SET CTY BIT
	CAIN	T3,FRCLIN##	;THIS THE LINE RESERVED FOR THE MONITOR?
	TLZ	T1,LDLLCT	;YES, IT IS ALWAYS LC
;[drp] provan, march 1, 1983: PTYs should try to avoid changing anything in
;[drp]			the character stream.
	CAILE	T3,TCONLN##	;ABOVE TCONLN?
;[drp]	TRO	T1,LDRPTY	;YES. SET PTY BIT
	  tdo	t1,[xwd <ldltab!ldlfrm!ldlnfc>,ldrpty]	;[drp] set bits on
	CAILE	T3,TCONLN##	;[drp] still a pty?
	  tlz	t1,ldllct	;[drp] make it lower case, too.
	IORM	T1,LDBDCH(U)	;PUT THESE BITS IN THE LDB
	PUSHJ	P,TYOVRG	;SETUP BYTE STREAM FOR OUTPUT
	PUSHJ	P,RECVRG	;AND FOR INPUT
	PUSHJ	P,TSETBI	;YES--CLEAR INPUT BUFFER
	HRLOI	T1,LPLCLR	;CLEAR PAGE BITS
	ANDCAM	T1,LDBPAG(U)	;...
	MOVSI	T1,LPLPAG	;INITIALIZE TERMINAL TO HANDLE XON/XOFF
	IORM	T1,LDBPAG(U)	;...
	MOVSI	T1,LPLALT	;THE ALTMODE-CONVERION BIT
	XCT	TTDALT##	;IORM OR ANDCAM DEPENDING ON DEFAULT
				; FOR TERMINAL ALT (SEE COMDEV)
IFN FTMIC,<SETZM LDBMIC(U)>	;CLEAR MIC WORD
	MOVSI	T3,L1LOFL	;OFF LINE BIT
	MOVEI	T1,ISROFL
	PUSHJ	P,@LDBISR(U)
	IORM	T3,LDBOFL(U)
	POPJ	P,0		;RETURN FROM LDBINI
	subttl	ScnSer support for ARPAnet

ifn FtCimp,<	;[arpa]

;[arpa] these are routine for the arpanet support which deal almost
;[arpa]	entirely with the SCNSER data base.  that's why they're here
;[arpa]	instead of in a arpanet module.  because they deal with the
;[arpa]	data base, they are the routines most likely to be affected
;[arpa]	but changes in ScnSer.

;[arpa]	these routines go one for several pages.

;[arpa]	still in IFN FtCImp
;[arpa]	still in IFN FtCImp

;[arpa] SUBROUTINE CALLED ONCE A MINUTE ON THE CLOCK TO LOOK
;[arpa] FOR LOST TELETYPE DDB'S AND RETURN THEM.  APPLIES TO IMP ITY'S AND DATASETS.
SCNMIN::MOVEI	F,TTYLST	;[arpa] POINT TO FIRST TTY DDB
SCNMN1:	PUSHJ	P,TTYKLQ	;[arpa] RETURN DDB IF LOST
	HLRZ	F,DEVSER(F)	;[arpa] ADVANCE TO NEXT DDB
	MOVE	T3,DEVMOD(F)	;[arpa] IS IT A TTY?
	TLNE	T3,DVTTY	;[arpa] ....
	  JRST	SCNMN1		;[arpa] YES - KEEP ON TRUCKING
	POPJ	P,		;[arpa] NO - EXUENT OMNI

;[arpa]	still in IFN FtCImp
;[arpa]	still in IFN FtCImp

;[arpa] SUBROUTINE TO CLEAR OUT LDB,DDB UPON LOSING A CONNECTION.
;[arpa]    APPLIES BOTH TO IMP AND DDB CONNECTIONS. ENTER WITH U
;[arpa]    POINTING TO DDB IN QUESTION.

DSCCLR::
	SKIPE	F,LDBIMP(U)	;[arpa] CROSSPATCHED TO IMP?
	  PUSHJ	P,TTIDET##	;[arpa] YES - PULL THE PLUG
	PUSHJ	P,LDBCLR	;[arpa] CLEAN OUT LDB STATUS
IFN FTLINK,<			;[link]
	PUSHJ	P,LNKBRK##	;[link] SHAKE OFF ANY EXISTING LINKS
>				;[link]
	PUSHJ	P,TSETBI	;[arpa] CLEAR INPUT
	PUSHJ	P,TSETBO	;[arpa]  AND OUTPUT BUFFERS
	HRRZ	F,LDBDDB(U)	;[arpa] SEE IF THERE'S A JOB
	JUMPE	F,CPOPJ##	;[arpa] NO
	MOVE	T1,DEVMOD(F)	;[arpa] MAY BE A JOB. GET MODE WORD
	TLNN	T1,TTYATC	;[arpa] IS TTY CONTROLLING A JOB?
	  POPJ	P,		;[arpa] NOT A CONTROLLING TTY
	SKIPE	T1,F
	  LDB	T1,PJOBN	;[arpa] GET JOB NUMBER
	MOVE	T2,JBTSTS##(T1)	;[arpa] GET JOB STATUS
	TLNN	T2,JLOG		;[arpa] IS JOB LOGGED IN?
	  JRST	DSCCL1		;[arpa] NO - STOP JOB BY SENDING REAL CTRL-C
	MOVEI	T3,TTFCXD	;[arpa] DETACH COMMAND INDEX
	DPB	T3,LDPCMX	;[arpa] STORE IN FORCED COMMAND INDEX BYTE
	MOVSI	T3,LDBCMR+LDBCMF ;[arpa] SET FORCED COMMAND BIT
	IORM	T3,(U)		;[arpa] FOR COMMAND SCANNER TO SEE
	AOS	COMCNT##	;[arpa] WAKE COMMAND DECODER
	PJRST	CMDSET		;[arpa] CALL COMMAND ROUTINE

;[arpa] HERE IF NOT LOGGED IN. SET ↑O BIT AND SEND ↑C, FOR PROGRAM TO
;[arpa]  INTERPRET AS IT WILL (IE, KILL LOGIN)
DSCCL1:	MOVSI	T1,LDLCOM 	;[arpa] CLEAR COM LEVEL BIT, SET ↑O BIT
	HRRI	T1,LDROSU	;[arpa]
	XORM	T1,LDBDCH(U)	;[arpa] (COM WAS SET BY LDBCLR)
	MOVEI	T3,"C"-100	;[arpa] SET UP A CTRL-C
	PJRST	RECIN1		;[arpa] JAM IT INTO INPUT

;[arpa]	still in IFN FtCImp
;[arpa]	still in IFN FtCImp


;[arpa] ROUTINE TO SET UP A TTY-TO-IMP CROSSPATCH (THEREAFTER ADDRESSED AS
;[arpa]  HIS NASTINESS)

;[arpa] 	MOVE	F,[IMP DDB ADDRESS]
;[arpa] 	MOVE	J, JOB NUMBER
;[arpa] 	PUSHJ	P,TTYIMP##
;[arpa] 	ALWAYS RETURN HERE (NO CONNECTION MADE IF ERROR)
;[arpa] 	  RETURNS LDB POINTER IN T1

TTYIMP::PUSH	P,U		;[arpa] SAVE OLD U (NEEDED BY NCP)
	SKIPE	U,TTYTAB(J)	;[arpa] GET TTY DDB ADDRESS
	  HRRZ	U,DDBLDB(U)	;[arpa] FOLLOW POINTER TO LDB
	JUMPE	U,TTYIM2	;[arpa] FORGET IF NONEXISTENT OR DETACHED
	LDB	T1,LDPLCL##	;[arpa] GET LOCAL ESCAPE CHARACTER
	JUMPN	T1,TTYIM1	;[arpa] IS THERE ONE DEFINED?
	MOVEI	T1,037		;[arpa] NO - PREVENT USER FROM NOT BEING ABLE TO
	DPB	T1,LDPLCL##	;[arpa] TO ESCAPE BY GIVING HIM DEFAULT (↑←)
TTYIM1:	HRRZM	F,LDBIMP(U)	;[arpa] STORE IMP POINTER IN LDB
TTYIM2:	MOVEI	T1,(U)		;[arpa] COPY LDB ADDRESS INTO T1
	JRST	UPOPJ##		;[arpa] RESTORE U AND RETURN

;[arpa]	still in IFN FtCImp
;[arpa]	still in IFN FtCImp


;[arpa] SUBROUTINE TO HANDLE TTY INPUT TO CROSSPATCHED TTY

TTIMPI:
	PUSHJ	P,RQTIIO##	;[arpa] REQUEST IMP PROCESSING OF TTY DATA
	SETZ	T1,		;[arpa] SIGNAL NOT A NORMAL BREAK CHAR
	POPJ	P,		;[arpa] RETURN

;[arpa]	still in IFN FtCImp
;[arpa]	still in IFN FtCImp

;[arpa] SUBROUTINE CALLED FROM IMP SERVICE TO GET A CHARACTER
;[arpa]   FROM THE INPUT BUFFER OF A CROSSPATCHED TTY.
;[arpa]   ENTER WITH LDB ADDRESS IN U.
;[arpa]   SKIP RETURNS 9-BIT CHAR IN T3.
;[arpa]   NON-SKIP RETURN IF NONE

TTYTTI::PUSH	P,S		;[arpa] IN CASE CLOCK1 REALLY CARES ABOUT S
	SETZ	S,		;[arpa] MAKE SURE TYI IS NOT FOOLED
	PUSHJ	P,TYI		;[arpa] GO GET THE CHARACTER
	 SKIPA			;[arpa] NONE LEFT
	  AOS	-1(P)		;[arpa] GOT A CHARACTER
	POP	P,S		;[arpa] RESTORE S
	POPJ	P,		;[arpa] AND RETURN

;[arpa]	still in IFN FtCImp
;[arpa]	still in IFN FtCImp

;[arpa] SUBROUTINE TO SEND A CHARACTER TO A TELETYPE BUFFER.

;[arpa] CALLED FROM IMP INTERRUPT LEVEL.
;[arpa]   ENTER WITH LDB ADDRESS IN U, CHAR IN T3.
;[arpa]   RETURN SKIP IF OK, NON-SKIP IF NO ROOM.

TTYXMT::HLL	U,LDBDCH(U)	;[arpa] GET CHARACTERISTICS
	MOVEI	T1,LDROSU	;[arpa] GET OSU BIT FIRST
	TDNE	T1,LDBDCH(U)	;[arpa] IS IT ON
	  PJRST	CPOPJ1##	;[arpa] YES - QUIT VERY QUICKLY
	MOVE	T1,TTFREN##	;[arpa] GET NO. OF CHUNKS AVAILABLE
	MOVE	T2,LDBTOC(U)	;[arpa] AND CHECK HOW MUCH NOW IN BUFFER
	CAIL	T1,3		;[arpa] ALWAYS LEAVE A LITTLE
	 CAML	T2,TIWRNN	;[arpa] AND DON'T GIVE TOO MUCH TO ONE TTY
	  POPJ	P,		;[arpa] TOO LITTLE OR TOO MUCH - TELL IMPSER TO STOP
	AOS	(P)		;[arpa] CONFIDENCE
	TRNN	T3,400		;[arpa] IMAGE CHARACTER?
	  PUSHJ	P,PEVEN8	;[arpa] NO - FIX PARITY
	PJRST	TYO9A		;[arpa] SEND, THEN GO BACK FOR MORE

;[arpa] STILL IN FTCIMP
;[arpa]	still in IFN FtCImp

;[arpa] ROUTINES TO SET/CLEAR THE NOECHO BIT IN DEVIOS, DOING THE APPROPRIATE
;[arpa]  LINE HANDLING. SENDING TELNET CONTROL CODES, ETC.

;[arpa] 	MOVE	U, LINE ADDR
;[arpa] 	PUSHJ	P,SETECH (TO CLEAR NOECHO)
;[arpa] 		  SETNEC (TO SET NOECHO)
;[arpa]		ALWAYS RETURN HERE.  F, S CLOBBERED

SETECH::TDZA	S,S		;[arpa] HERE TO CLEAR THE BIT
SETNEC::MOVEI	S,IOSNEC	;[arpa] HERE TO SET THE BIT
	HRRZ	F,LDBDDB(U)	;[arpa] LOOK FOR THE ATTACHED TTY DDB
	JUMPE	F,UUOLDB	;[arpa] NOT AROUND (SHOULD NEVER HAPPEN)
	IORM	S,DEVIOS(F)	;[arpa] SET BIT IF SETTING
	XORI	S,IOSNEC	;[arpa] CLEAR BIT IF CLEARING (GETTIN' DIZZY)
	ANDCAB	S,DEVIOS(F)	;[arpa]
	PJRST	UUOLDB		;[arpa] MAKE LDB BITS AGREE WITH S BITS

> ;[arpa] END FTCIMP
	SUBTTL	IMPURE DATA

	$LOW
ECHCNT:	0			;CLOCK REQUEST QUEUE COUNTER
TTBASE::0			;FIRST WORD IN TERMINAL BUFFER SPACE
IFN FTDIAL,<
DSCNUM:	BLOCK	2		;PHONE NUMBER BEING DIALLED, OR LAST DIALLED
>

.GTSCN::
;SCNSER RESPONSE DATA (%SC??? VALID ONLY IF FTRSP!FTACCT)
%SCNRI::0			;(0)  NUMBER OF CHARS (EXCLUDES MIC) RECEIVED
%SCNXI::0			;(1)  NUMBER OF CHARS (INCLUDES FILL) XMITTED
%SCNEI::0			;(2)  NUMBER OF CHARS ECHOED (SUBSET OF %SCNXI)
TIWRNN::EXP	TTIBRK		;(3)  MAX BUFFER SIZE
%SCNAL::0			;(4)  NUMBER OF ACTIVE LINES
RPIMWN::EXP	↑D600		;(5)  PIM BUFFER SIZE
	EXP	RECINT		;(6)  FOR MONITOR TEST
	EXP	XMTINT		;(7)  PROGRAMS
	EXP	0		;(10) WAS TYPEX
TTFTAK::0			;(11) FIRST FREE CHUNK
TTFPUT::0			;(12) LAST FREE CHUNK
SCNMXL==:<<.-.GTSCN-1>B26>
TIWRN1:	↑D80			;WORD TO SAVE OLD BUFFER LIMIT
	XLIST			;LITERALS UNDER XLIST
	$LIT
	LIST

SCNEND:	END